Skip to content

Commit 24e081c

Browse files
committed
Merge pull request #10 from rneatherway/completion_filtering
Completion filtering
2 parents 2c13fb9 + 590cb93 commit 24e081c

File tree

25 files changed

+1094
-143
lines changed

25 files changed

+1094
-143
lines changed

FSharp.AutoComplete/Makefile

Lines changed: 0 additions & 20 deletions
This file was deleted.

FSharp.AutoComplete/Program.fs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ module internal CommandInput =
117117
Optional 'sync' is used to force the parse to occur
118118
synchronously for testing purposes. Not intended for
119119
use in production.
120-
completion ""<filename>"" <line> <col> [timeout]
120+
completion ""<filename>"" <line> <col> [timeout] [filter=(StartsWith|Contains)]
121121
- trigger completion request for the specified location
122+
optionally filter in the specified manner
122123
helptext <candidate>
123124
- fetch type signature for specified completion candidate
124125
(from last completion request). Only use in JSON mode.
@@ -172,7 +173,7 @@ module internal CommandInput =
172173

173174
// Command that can be entered on the command-line
174175
type Command =
175-
| PosCommand of PosCommand * string * int * int * int option
176+
| PosCommand of PosCommand * string * int * int * int option * string option
176177
| HelpText of string
177178
| Declarations of string
178179
| Parse of string * ParseKind
@@ -248,7 +249,14 @@ module internal CommandInput =
248249
(parser { let! _ = some (string " ")
249250
return! some digit |> Parser.map (String.ofSeq >> int >> Some) }) <|>
250251
(parser { return None })
251-
return PosCommand(f, filename, line, col, timeout) }
252+
let! filter =
253+
(parser { let! _ = many (string " ")
254+
let! _ = string "filter="
255+
let! b = (string "StartsWith" <|> string "Contains")
256+
|> Parser.map String.ofSeq
257+
return Some b }) <|>
258+
(parser { return None })
259+
return PosCommand(f, filename, line, col, timeout, filter) }
252260

253261
let helptext = parser {
254262
let! _ = string "helptext"
@@ -509,7 +517,7 @@ module internal Main =
509517

510518
main state
511519

512-
| PosCommand(cmd, file, line, col, timeout) ->
520+
| PosCommand(cmd, file, line, col, timeout, filter) ->
513521
let file = Path.GetFullPath file
514522
if parsed file && posok file line col then
515523
let text, projFile, args = getoptions file state
@@ -527,29 +535,34 @@ module internal Main =
527535

528536
match tyRes.GetDeclarations(line, col, lineStr) with
529537
| Some (decls, residue) ->
538+
let decls =
539+
match filter with
540+
| Some "StartsWith" -> [| for d in decls.Items do if d.Name.StartsWith residue then yield d |]
541+
| Some "Contains" -> [| for d in decls.Items do if d.Name.Contains residue then yield d |]
542+
| _ -> decls.Items
543+
530544
match state.OutputMode with
531545
| Text ->
532546
printAgent.WriteLine "DATA: completion"
533-
for d in decls.Items do printAgent.WriteLine(d.Name)
547+
for d in decls do printAgent.WriteLine(d.Name)
534548
printAgent.WriteLine "<<EOF>>"
535549
main state
536550
| Json ->
537551

538-
let ds = List.sortBy (fun (d: FSharpDeclarationListItem) -> d.Name)
539-
[ for d in decls.Items do yield d ]
540-
match List.tryFind (fun (d: FSharpDeclarationListItem) -> d.Name.StartsWith residue) ds with
552+
let ds = Array.sortBy (fun (d: FSharpDeclarationListItem) -> d.Name) decls
553+
match Array.tryFind (fun (d: FSharpDeclarationListItem) -> d.Name.StartsWith residue) ds with
541554
| None -> ()
542555
| Some d -> let tip = TipFormatter.formatTip d.DescriptionText
543556
let helptext = Map.add d.Name tip Map.empty
544557
prAsJson { Kind = "helptext"; Data = helptext }
545558

546559
prAsJson { Kind = "completion"
547-
Data = [ for d in decls.Items do
560+
Data = [ for d in decls do
548561
let (glyph, glyphChar) = CompletionUtils.getIcon d.Glyph
549562
yield { Name = d.Name; Glyph = glyph; GlyphChar = glyphChar } ] }
550563

551564
let helptext =
552-
Seq.fold (fun m (d: FSharpDeclarationListItem) -> Map.add d.Name d.DescriptionText m) Map.empty decls.Items
565+
Seq.fold (fun m (d: FSharpDeclarationListItem) -> Map.add d.Name d.DescriptionText m) Map.empty decls
553566

554567
main { state with HelpText = helptext }
555568
| None ->
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#load "../TestHelpers.fsx"
2+
open TestHelpers
3+
open System.IO
4+
open System
5+
6+
(*
7+
* This test is a simple sanity check of a basic run of the program.
8+
* A few completions, files and script.
9+
*)
10+
11+
Environment.CurrentDirectory <- __SOURCE_DIRECTORY__
12+
File.Delete "output.txt"
13+
14+
let p = new FSharpAutoCompleteWrapper()
15+
16+
p.parse "Script.fsx"
17+
p.completion "Script.fsx" 2 6
18+
p.completionFilter "Script.fsx" 2 6 "StartsWith"
19+
p.completionFilter "Script.fsx" 2 6 "Contains"
20+
p.send "quit\n"
21+
p.finalOutput ()
22+
|> writeNormalizedOutput "output.txt"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
List.c
3+
4+
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
INFO: Synchronous parsing started
2+
<<EOF>>
3+
DATA: errors
4+
[2:5-2:6] ERROR The value, constructor, namespace or type 'c' is not defined
5+
<<EOF>>
6+
DATA: completion
7+
Cons
8+
Empty
9+
append
10+
average
11+
averageBy
12+
choose
13+
collect
14+
concat
15+
empty
16+
exists
17+
exists2
18+
filter
19+
find
20+
findIndex
21+
fold
22+
fold2
23+
foldBack
24+
foldBack2
25+
forall
26+
forall2
27+
head
28+
init
29+
isEmpty
30+
iter
31+
iter2
32+
iteri
33+
iteri2
34+
length
35+
map
36+
map2
37+
map3
38+
mapi
39+
mapi2
40+
max
41+
maxBy
42+
min
43+
minBy
44+
nth
45+
ofArray
46+
ofSeq
47+
partition
48+
permute
49+
pick
50+
reduce
51+
reduceBack
52+
replicate
53+
rev
54+
scan
55+
scanBack
56+
sort
57+
sortBy
58+
sortWith
59+
sum
60+
sumBy
61+
tail
62+
toArray
63+
toSeq
64+
tryFind
65+
tryFindIndex
66+
tryPick
67+
unzip
68+
unzip3
69+
zip
70+
zip3
71+
<<EOF>>
72+
DATA: completion
73+
choose
74+
collect
75+
concat
76+
<<EOF>>
77+
DATA: completion
78+
choose
79+
collect
80+
concat
81+
foldBack
82+
foldBack2
83+
pick
84+
reduce
85+
reduceBack
86+
replicate
87+
scan
88+
scanBack
89+
tryPick
90+
<<EOF>>

FSharp.AutoComplete/test/integration/ErrorTests/ErrorsRunner.fsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ p.completion "Program.fs" 6 13
1414
p.parse "Script.fsx"
1515
p.completion "Script.fsx" 6 13
1616
p.send "quit\n"
17-
let output = p.finalOutput ()
18-
File.WriteAllText("output.txt", output)
17+
p.finalOutput ()
18+
|> writeNormalizedOutput "output.txt"
1919

FSharp.AutoComplete/test/integration/ErrorTestsJson/ErrorsRunner.fsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ Threading.Thread.Sleep(8000)
1616
p.completion "Program.fs" 6 13
1717
p.completion "Script.fsx" 6 13
1818
p.send "quit\n"
19-
let output = p.finalOutput ()
20-
File.WriteAllText("output.json", output)
19+
p.finalOutput ()
20+
|> writeNormalizedOutput "output.json"
2121

Lines changed: 116 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,116 @@
1-
{"Kind":"project","Data":{"Project":"<absolute path removed>/test/integration/ErrorTestsJson/Test1.fsproj","Files":["<absolute path removed>/test/integration/ErrorTestsJson/FileTwo.fs","<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"],"Output":"<absolute path removed>/test/integration/ErrorTestsJson/bin/Debug/Test1.exe","References":["<absolute path removed>/FSharp.Core.dll","<absolute path removed>/System.Core.dll","<absolute path removed>/System.dll","<absolute path removed>/mscorlib.dll"],"Framework":"v4.0"}}
2-
{"Kind":"INFO","Data":"Synchronous parsing started"}
3-
{"Kind":"errors","Data":[{"StartLine":3,"StartLineAlternate":4,"EndLine":3,"EndLineAlternate":4,"StartColumn":14,"EndColumn":21,"Severity":"Error","Message":"The namespace or module 'FileTwo' is not defined","Subcategory":"typecheck","FileName":"<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"},{"StartLine":7,"StartLineAlternate":8,"EndLine":7,"EndLineAlternate":8,"StartColumn":11,"EndColumn":27,"Severity":"Error","Message":"Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.","Subcategory":"typecheck","FileName":"<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"},{"StartLine":9,"StartLineAlternate":10,"EndLine":9,"EndLineAlternate":10,"StartColumn":18,"EndColumn":22,"Severity":"Error","Message":"This expression was expected to have type\n int \nbut here has type\n string ","Subcategory":"typecheck","FileName":"<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"}]}
4-
{"Kind":"INFO","Data":"Synchronous parsing started"}
5-
{"Kind":"errors","Data":[{"StartLine":7,"StartLineAlternate":8,"EndLine":7,"EndLineAlternate":8,"StartColumn":12,"EndColumn":19,"Severity":"Error","Message":"The value or constructor 'unnamed' is not defined","Subcategory":"typecheck","FileName":"<absolute path removed>/test/integration/ErrorTestsJson/Script.fsx"}]}
6-
{"Kind":"helptext","Data":{"func":"val func : x:int -> int"}}
7-
{"Kind":"completion","Data":[{"Name":"func","Glyph":"Method","GlyphChar":"M"}]}
8-
{"Kind":"helptext","Data":{"func":"val func : x:int -> int"}}
9-
{"Kind":"completion","Data":[{"Name":"func","Glyph":"Method","GlyphChar":"M"}]}
1+
{
2+
"Kind": "project",
3+
"Data": {
4+
"Project": "<absolute path removed>/test/integration/ErrorTestsJson/Test1.fsproj",
5+
"Files": [
6+
"<absolute path removed>/test/integration/ErrorTestsJson/FileTwo.fs",
7+
"<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"
8+
],
9+
"Output": "<absolute path removed>/test/integration/ErrorTestsJson/bin/Debug/Test1.exe",
10+
"References": [
11+
"<absolute path removed>/FSharp.Core.dll",
12+
"<absolute path removed>/System.Core.dll",
13+
"<absolute path removed>/System.dll",
14+
"<absolute path removed>/mscorlib.dll"
15+
],
16+
"Framework": "v4.0"
17+
}
18+
}
19+
{
20+
"Kind": "INFO",
21+
"Data": "Synchronous parsing started"
22+
}
23+
{
24+
"Kind": "errors",
25+
"Data": [
26+
{
27+
"StartLine": 3,
28+
"StartLineAlternate": 4,
29+
"EndLine": 3,
30+
"EndLineAlternate": 4,
31+
"StartColumn": 14,
32+
"EndColumn": 21,
33+
"Severity": "Error",
34+
"Message": "The namespace or module 'FileTwo' is not defined",
35+
"Subcategory": "typecheck",
36+
"FileName": "<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"
37+
},
38+
{
39+
"StartLine": 7,
40+
"StartLineAlternate": 8,
41+
"EndLine": 7,
42+
"EndLineAlternate": 8,
43+
"StartColumn": 11,
44+
"EndColumn": 27,
45+
"Severity": "Error",
46+
"Message": "Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.",
47+
"Subcategory": "typecheck",
48+
"FileName": "<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"
49+
},
50+
{
51+
"StartLine": 9,
52+
"StartLineAlternate": 10,
53+
"EndLine": 9,
54+
"EndLineAlternate": 10,
55+
"StartColumn": 18,
56+
"EndColumn": 22,
57+
"Severity": "Error",
58+
"Message": "This expression was expected to have type\n int \nbut here has type\n string ",
59+
"Subcategory": "typecheck",
60+
"FileName": "<absolute path removed>/test/integration/ErrorTestsJson/Program.fs"
61+
}
62+
]
63+
}
64+
{
65+
"Kind": "INFO",
66+
"Data": "Synchronous parsing started"
67+
}
68+
{
69+
"Kind": "errors",
70+
"Data": [
71+
{
72+
"StartLine": 7,
73+
"StartLineAlternate": 8,
74+
"EndLine": 7,
75+
"EndLineAlternate": 8,
76+
"StartColumn": 12,
77+
"EndColumn": 19,
78+
"Severity": "Error",
79+
"Message": "The value or constructor 'unnamed' is not defined",
80+
"Subcategory": "typecheck",
81+
"FileName": "<absolute path removed>/test/integration/ErrorTestsJson/Script.fsx"
82+
}
83+
]
84+
}
85+
{
86+
"Kind": "helptext",
87+
"Data": {
88+
"func": "val func : x:int -> int"
89+
}
90+
}
91+
{
92+
"Kind": "completion",
93+
"Data": [
94+
{
95+
"Name": "func",
96+
"Glyph": "Method",
97+
"GlyphChar": "M"
98+
}
99+
]
100+
}
101+
{
102+
"Kind": "helptext",
103+
"Data": {
104+
"func": "val func : x:int -> int"
105+
}
106+
}
107+
{
108+
"Kind": "completion",
109+
"Data": [
110+
{
111+
"Name": "func",
112+
"Glyph": "Method",
113+
"GlyphChar": "M"
114+
}
115+
]
116+
}

FSharp.AutoComplete/test/integration/FindDeclarations/FindDeclRunner.fsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ p.finddeclaration "Program.fs" 14 25
2323
p.finddeclaration "Program.fs" 10 19
2424
p.finddeclaration "Script.fsx" 6 16
2525
p.send "quit\n"
26-
let output = p.finalOutput ()
27-
File.WriteAllText("output.txt", output)
26+
p.finalOutput ()
27+
|> writeNormalizedOutput "output.txt"

FSharp.AutoComplete/test/integration/MultiProj/MultiProjRunner.fsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ p.completion "Proj2/Program.fs" 6 13
3939
p.completion "Proj2/Program.fs" 10 19
4040

4141
p.send "quit\n"
42-
let output = p.finalOutput ()
43-
File.WriteAllText("output.txt", output)
42+
p.finalOutput ()
43+
|> writeNormalizedOutput "output.txt"
4444

0 commit comments

Comments
 (0)