提交 a1126d49 编写于 作者: V Vasily Kirichenko 提交者: Kevin Ransom (msft)

Fix quick info for active pattern definition (#2809)

* fix quick info for active pattern definition

* all features work on individual active pattern results again
上级 86a81b9a
......@@ -101,7 +101,7 @@ type internal FSharpAddOpenCodeFixProvider
let! symbol =
asyncMaybe {
let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, context.Span.End, document.FilePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, context.Span.End, document.FilePath, defines, SymbolLookupKind.Greedy, false)
return! checkResults.GetSymbolUseAtLocation(Line.fromZ linePos.Line, lexerSymbol.Ident.idRange.EndColumn, line.ToString(), lexerSymbol.FullIsland)
} |> liftAsync
......
......@@ -169,7 +169,7 @@ type internal FSharpImplementInterfaceCodeFixProvider
| _ ->
Some context.Span.End
let! interfaceState = queryInterfaceState appendBracketAt interfacePos tokens parsedInput
let! symbol = Tokenizer.getSymbolAtPosition(context.Document.Id, sourceText, fixupPosition, context.Document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(context.Document.Id, sourceText, fixupPosition, context.Document.FilePath, defines, SymbolLookupKind.Greedy, false)
let fcsTextLineNumber = textLine.LineNumber + 1
let lineContents = textLine.ToString()
let! options = context.Document.GetOptionsAsync(cancellationToken)
......
......@@ -56,7 +56,7 @@ type internal FSharpDocumentHighlightsService [<ImportingConstructor>] (checkerP
let textLine = sourceText.Lines.GetLineFromPosition(position)
let textLinePos = sourceText.Lines.GetLinePosition(position)
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! symbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy, false)
let! _, _, checkFileResults = checker.ParseAndCheckDocument(filePath, textVersionHash, sourceText.ToString(), options, allowStaleResults = true)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland)
let! symbolUses = checkFileResults.GetUsesOfSymbolInFile(symbolUse.Symbol) |> liftAsync
......
......@@ -150,7 +150,7 @@ type internal InlineRenameService
let textLine = sourceText.Lines.GetLineFromPosition(position)
let textLinePos = sourceText.Lines.GetLinePosition(position)
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false)
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, options, allowStaleResults = true)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.Text.ToString(), symbol.FullIsland)
let! declLoc = symbolUse.GetDeclarationLocation(document)
......
......@@ -65,7 +65,7 @@ module internal SymbolHelpers =
do! Option.guard (originalText.Length > 0)
let! options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject document
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.Name, options.OtherOptions |> Seq.toList)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, symbolSpan.Start, document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, symbolSpan.Start, document.FilePath, defines, SymbolLookupKind.Greedy, false)
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, options, allowStaleResults = true)
let textLine = sourceText.Lines.GetLineFromPosition(symbolSpan.Start)
let textLinePos = sourceText.Lines.GetLinePosition(symbolSpan.Start)
......
......@@ -23,6 +23,7 @@ type internal LexerSymbolKind =
| Punctuation
| GenericTypeParameter
| StaticallyResolvedTypeParameter
| ActivePattern
| Other
type internal LexerSymbol =
......@@ -388,12 +389,22 @@ module internal Tokenizer =
{ Kind = kind; Token = token; RightColumn = token.LeftColumn + token.FullMatchedLength - 1 }
/// Returns symbol at a given position.
let private getSymbolFromTokens (fileName: string, tokens: FSharpTokenInfo list, linePos: LinePosition, lineStr: string, lookupKind: SymbolLookupKind) : LexerSymbol option =
let private getSymbolFromTokens
(
fileName: string,
tokens: FSharpTokenInfo list,
linePos: LinePosition,
lineStr: string,
lookupKind: SymbolLookupKind,
wholeActivePatterns: bool
)
: LexerSymbol option =
let isIdentifier t = t.CharClass = FSharpTokenCharKind.Identifier
let isOperator t = t.ColorClass = FSharpTokenColorKind.Operator
let isPunctuation t = t.ColorClass = FSharpTokenColorKind.Punctuation
let inline (|GenericTypeParameterPrefix|StaticallyResolvedTypeParameterPrefix|Other|) (token: FSharpTokenInfo) =
let inline (|GenericTypeParameterPrefix|StaticallyResolvedTypeParameterPrefix|ActivePattern|Other|) (token: FSharpTokenInfo) =
if token.Tag = FSharpTokenTag.QUOTE then GenericTypeParameterPrefix
elif token.Tag = FSharpTokenTag.INFIX_AT_HAT_OP then
// The lexer return INFIX_AT_HAT_OP token for both "^" and "@" symbols.
......@@ -401,6 +412,10 @@ module internal Tokenizer =
if token.FullMatchedLength = 1 && lineStr.[token.LeftColumn] = '^' then
StaticallyResolvedTypeParameterPrefix
else Other
elif token.Tag = FSharpTokenTag.LPAREN then
if token.FullMatchedLength = 1 && lineStr.[token.LeftColumn+1] = '|' then
ActivePattern
else Other
else Other
// Operators: Filter out overlapped operators (>>= operator is tokenized as three distinct tokens: GREATER, GREATER, EQUALS.
......@@ -419,11 +434,22 @@ module internal Tokenizer =
|> List.foldi (fun (acc, lastToken) index (token: FSharpTokenInfo) ->
match lastToken with
| Some t when token.LeftColumn <= t.RightColumn -> acc, lastToken
| Some ({ Kind = LexerSymbolKind.ActivePattern } as lastToken) when
wholeActivePatterns &&
(token.Tag = FSharpTokenTag.BAR || token.Tag = FSharpTokenTag.IDENT || token.Tag = FSharpTokenTag.UNDERSCORE) ->
let mergedToken =
{lastToken.Token with Tag = FSharpTokenTag.IDENT
RightColumn = token.RightColumn
FullMatchedLength = lastToken.Token.FullMatchedLength + token.FullMatchedLength }
acc, Some { lastToken with Token = mergedToken; RightColumn = lastToken.RightColumn + token.FullMatchedLength }
| _ ->
let isLastToken = index = tokensCount - 1
match token with
| GenericTypeParameterPrefix when not isLastToken -> acc, Some (DraftToken.Create LexerSymbolKind.GenericTypeParameter token)
| StaticallyResolvedTypeParameterPrefix when not isLastToken -> acc, Some (DraftToken.Create LexerSymbolKind.StaticallyResolvedTypeParameter token)
| ActivePattern when wholeActivePatterns -> acc, Some (DraftToken.Create LexerSymbolKind.ActivePattern token)
| _ ->
let draftToken =
match lastToken with
......@@ -434,6 +460,8 @@ module internal Tokenizer =
| Some { Kind = LexerSymbolKind.StaticallyResolvedTypeParameter } ->
DraftToken.Create LexerSymbolKind.Operator { token with LeftColumn = token.LeftColumn - 1
FullMatchedLength = 1 }
| Some ( { Kind = LexerSymbolKind.ActivePattern } as ap) when wholeActivePatterns && token.Tag = FSharpTokenTag.RPAREN ->
DraftToken.Create LexerSymbolKind.Ident ap.Token
| _ ->
let kind =
if isOperator token then LexerSymbolKind.Operator
......@@ -459,7 +487,8 @@ module internal Tokenizer =
tokensUnderCursor
|> List.tryFind (fun { DraftToken.Kind = k } ->
match k with
| LexerSymbolKind.Ident
| LexerSymbolKind.Ident
| LexerSymbolKind.ActivePattern
| LexerSymbolKind.GenericTypeParameter
| LexerSymbolKind.StaticallyResolvedTypeParameter -> true
| _ -> false)
......@@ -519,10 +548,21 @@ module internal Tokenizer =
Assert.Exception(ex)
[]
let getSymbolAtPosition(documentKey: DocumentId, sourceText: SourceText, position: int, fileName: string, defines: string list, lookupKind: SymbolLookupKind) : LexerSymbol option =
let getSymbolAtPosition
(
documentKey: DocumentId,
sourceText: SourceText,
position: int,
fileName: string,
defines: string list,
lookupKind: SymbolLookupKind,
wholeActivePatterns: bool
)
: LexerSymbol option =
try
let lineData, textLinePos, lineContents = getCachedSourceLineData(documentKey, sourceText, position, fileName, defines)
getSymbolFromTokens(fileName, lineData.Tokens, textLinePos, lineContents, lookupKind)
getSymbolFromTokens(fileName, lineData.Tokens, textLinePos, lineContents, lookupKind, wholeActivePatterns)
with
| :? System.OperationCanceledException -> reraise()
| ex ->
......@@ -582,7 +622,7 @@ module internal Tokenizer =
| LexerSymbolKind.Punctuation, _ -> PrettyNaming.IsPunctuation name
| LexerSymbolKind.GenericTypeParameter, _ -> isGenericTypeParameter name
| LexerSymbolKind.StaticallyResolvedTypeParameter, _ -> isStaticallyResolvedTypeParameter name
| (LexerSymbolKind.Ident | LexerSymbolKind.Other), _ ->
| (LexerSymbolKind.Ident | LexerSymbolKind.ActivePattern | LexerSymbolKind.Other), _ ->
match symbol with
| :? FSharpEntity as e when e.IsClass || e.IsFSharpRecord || e.IsFSharpUnion || e.IsValueType || e.IsFSharpModule || e.IsInterface -> isTypeNameIdent name
| _ -> isFixableIdentifier name
......@@ -54,7 +54,7 @@ type internal FSharpFindUsagesService
let lineNumber = sourceText.Lines.GetLinePosition(position).Line + 1
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.FilePath, options.OtherOptions |> Seq.toList)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(lineNumber, symbol.Ident.idRange.EndColumn, textLine, symbol.FullIsland)
let! declaration = checkFileResults.GetDeclarationLocationAlternate (lineNumber, symbol.Ident.idRange.EndColumn, textLine, symbol.FullIsland, false) |> liftAsync
let tags = GlyphTags.GetTags(Tokenizer.GetGlyphForSymbol (symbolUse.Symbol, symbol.Kind))
......
......@@ -45,7 +45,7 @@ module internal FSharpGoToDefinition =
let textLine = sourceText.Lines.GetLineFromPosition position
let textLinePos = sourceText.Lines.GetLinePosition position
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy, false)
let! _, _, checkFileResults =
checker.ParseAndCheckDocument
(filePath, textVersionHash, sourceText.ToString(), options, allowStaleResults = preferSignature)
......@@ -84,7 +84,7 @@ module internal FSharpGoToDefinition =
let defines = CompilerEnvironment.GetCompilationDefinesForEditing (originDocument.FilePath, projectOptions.OtherOptions |> Seq.toList)
let originTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sourceText, originRange)
let position = originTextSpan.Start
let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position, originDocument.FilePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position, originDocument.FilePath, defines, SymbolLookupKind.Greedy, false)
let textLinePos = sourceText.Lines.GetLinePosition position
let fcsTextLineNumber = Line.fromZ textLinePos.Line
......@@ -245,7 +245,7 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
let textLine = sourceText.Lines.GetLineFromPosition position
let textLinePos = sourceText.Lines.GetLinePosition position
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy, false)
let! _, _, checkFileResults =
checker.ParseAndCheckDocument
(filePath, textVersionHash, sourceText.ToString(), options, allowStaleResults = true) |> Async.RunSynchronously
......@@ -278,7 +278,7 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
let! _, _, checkFileResults =
checkerProvider.Checker.ParseAndCheckDocument (originDocument, projectOptions, allowStaleResults=true, sourceText=sourceText)
let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position,originDocument.FilePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position,originDocument.FilePath, defines, SymbolLookupKind.Greedy, false)
let idRange = lexerSymbol.Ident.idRange
let! declarations =
......
......@@ -114,7 +114,7 @@ module private FSharpQuickInfo =
// project options need to be retrieved because the signature file could be in another project
let! extProjectOptions = projectInfoManager.TryGetOptionsForProject extDocId.ProjectId
let extDefines = CompilerEnvironment.GetCompilationDefinesForEditing (extDocument.FilePath, List.ofSeq extProjectOptions.OtherOptions)
let! extLexerSymbol = Tokenizer.getSymbolAtPosition(extDocId, extSourceText, extSpan.Start, declRange.FileName, extDefines, SymbolLookupKind.Greedy)
let! extLexerSymbol = Tokenizer.getSymbolAtPosition(extDocId, extSourceText, extSpan.Start, declRange.FileName, extDefines, SymbolLookupKind.Greedy, true)
let! _, _, extCheckFileResults = checker.ParseAndCheckDocument(extDocument,extProjectOptions,allowStaleResults=true,sourceText=extSourceText)
let! extTooltipText =
......@@ -149,7 +149,7 @@ module private FSharpQuickInfo =
let! sourceText = document.GetTextAsync cancellationToken
let! projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject document
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.FilePath, projectOptions.OtherOptions |> Seq.toList)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, true)
let idRange = lexerSymbol.Ident.idRange
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, projectOptions, allowStaleResults = true, sourceText=sourceText)
let textLinePos = sourceText.Lines.GetLinePosition position
......@@ -305,7 +305,7 @@ type internal FSharpQuickInfoProvider
let textLine = sourceText.Lines.GetLineFromPosition position
let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based
let defines = CompilerEnvironment.GetCompilationDefinesForEditing (filePath, options.OtherOptions |> Seq.toList)
let! symbol = Tokenizer.getSymbolAtPosition (documentId, sourceText, position, filePath, defines, SymbolLookupKind.Precise)
let! symbol = Tokenizer.getSymbolAtPosition (documentId, sourceText, position, filePath, defines, SymbolLookupKind.Precise, true)
let! res = checkFileResults.GetStructuredToolTipTextAlternate (textLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland, FSharpTokenTag.IDENT) |> liftAsync
match res with
| FSharpToolTipText []
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册