提交 94c7fe1f 编写于 作者: P Phillip Carter 提交者: Will Smith

Do not trigger completion on operators (#4054)

* No triggered completion on operators

* Check with classification data instead of stupid custom stuff

* Fix silly tests

* Feedback
上级 6e8515fc
......@@ -84,17 +84,17 @@ type internal FSharpCompletionProvider
// Skip if we are not on a completion trigger
else
let triggerPosition = caretPosition - 1
let c = sourceText.[triggerPosition]
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 && sourceText.[triggerPosition - 1] = '.' then
if not Settings.IntelliSense.ShowAfterCharIsTyped && prevChar = '.' then
false
// Trigger completion if we are on a valid classification type
else
let documentId, filePath, defines = getInfo()
CompletionUtils.shouldProvideCompletion(documentId, filePath, defines, sourceText, triggerPosition) &&
(c = '.' || (Settings.IntelliSense.ShowAfterCharIsTyped && CompletionUtils.isStartingNewWord(sourceText, triggerPosition)))
(triggerChar = '.' || (Settings.IntelliSense.ShowAfterCharIsTyped && CompletionUtils.isStartingNewWord(sourceText, triggerPosition)))
static member ProvideCompletionsAsyncAux(checker: FSharpChecker, sourceText: SourceText, caretPosition: int, options: FSharpProjectOptions, filePath: string,
textVersionHash: int, getAllSymbols: unit -> AssemblySymbol list) =
......
......@@ -82,18 +82,19 @@ module internal CompletionUtils =
let isStartingNewWord (sourceText, position) =
CommonCompletionUtilities.IsStartingNewWord(sourceText, position, (fun ch -> isIdentifierStartCharacter ch), (fun ch -> isIdentifierPartCharacter ch))
let shouldProvideCompletion (documentId: DocumentId, filePath: string, defines: string list, text: SourceText, position: int) : bool =
let textLines = text.Lines
let triggerLine = textLines.GetLineFromPosition position
let colorizationData = Tokenizer.getColorizationData(documentId, text, triggerLine.Span, Some filePath, defines, CancellationToken.None)
let shouldProvideCompletion (documentId: DocumentId, filePath: string, defines: string list, sourceText: SourceText, triggerPosition: int) : bool =
let textLines = sourceText.Lines
let triggerLine = textLines.GetLineFromPosition triggerPosition
let colorizationData = Tokenizer.getColorizationData(documentId, sourceText, triggerLine.Span, Some filePath, defines, CancellationToken.None)
colorizationData.Count = 0 || // we should provide completion at the start of empty line, where there are no tokens at all
colorizationData.Exists (fun classifiedSpan ->
classifiedSpan.TextSpan.IntersectsWith position &&
classifiedSpan.TextSpan.IntersectsWith triggerPosition &&
(
match classifiedSpan.ClassificationType with
| ClassificationTypeNames.Comment
| ClassificationTypeNames.StringLiteral
| ClassificationTypeNames.ExcludedCode
| ClassificationTypeNames.Operator
| ClassificationTypeNames.NumericLiteral -> false
| _ -> true // anything else is a valid classification type
))
\ No newline at end of file
......@@ -196,6 +196,83 @@ System.Console.WriteLine()
let triggered = FSharpCompletionProvider.ShouldTriggerCompletionAux(SourceText.From(fileContents), caretPosition, CompletionTriggerKind.Insertion, getInfo)
Assert.IsFalse(triggered, "FSharpCompletionProvider.ShouldTriggerCompletionAux() should not trigger")
[<Test>]
let ShouldNotTriggerCompletionInOperatorWithDot() =
// Simulate mistyping '|>' as '|.'
let fileContents = """
let f() =
12.0 |. sqrt
"""
let caretPosition = fileContents.IndexOf("|.")
let documentId = DocumentId.CreateNewId(ProjectId.CreateNewId())
let getInfo() = documentId, filePath, []
let triggered = FSharpCompletionProvider.ShouldTriggerCompletionAux(SourceText.From(fileContents), caretPosition, CompletionTriggerKind.Insertion, getInfo)
Assert.IsFalse(triggered, "FSharpCompletionProvider.ShouldTriggerCompletionAux() should not trigger on operators")
[<Test>]
let ShouldTriggerCompletionInAttribute() =
let fileContents = """
[<A
module Foo = module end
"""
let marker = "A"
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 on Attributes.")
[<Test>]
let ShouldTriggerCompletionAfterDerefOperator() =
let fileContents = """
let foo = ref 12
printfn "%d" !f
"""
let marker = "!f"
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 identifier that follows a dereference operator (!).")
[<Test>]
let ShouldTriggerCompletionAfterAddressOfOperator() =
let fileContents = """
type Point = { mutable X: int; mutable Y: int }
let pnt = { X = 1; Y = 2 }
use ptr = fixed &p
"""
let marker = "&p"
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 identifier that follows an addressOf operator (&).")
[<Test>]
let ShouldTriggerCompletionAfterArithmeticOperation() =
let fileContents = """
let xVal = 1.0
let yVal = 2.0
let zVal
xVal+y
xVal-y
xVal*y
xVal/y
xVal%y
xVal**y
"""
let markers = [ "+y"; "-y"; "*y"; "/y"; "%y"; "**y"]
for marker in markers do
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 identifier that follows a mathematical operation")
[<Test>]
let ShouldDisplayTypeMembers() =
let fileContents = """
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册