FsInteractiveService


Getting IntelliSense via HTTP API

This page gives a very brief overview of the IntelliSense commands exposed by the FsInteractiveService.exe server. The server exposes endpoints:

  • /completion - get auto-completion list at the specified location
  • /tooltip - get tooltip for item from previously obtained auto-completion list
  • /paramhints - get hint method parameters (on opening bracket)
  • endpoints for evaluating snippets are discussed on a separate page

In this tutorial, we assume we already have the FsInteractiveService.exe process running on port 18083. For more information about starting the server, see running snippets using FsInteractiveService via HTTP.

Getting completion on namespaces

The /completion command can be used to get auto-completion information in F# Interactive. For example, if the user types Microsoft.FSharp., we can get the completion on the types and other entities in the namespace.. For that, call /completion with body containing sourceLine (with the text on the current line of the input) and column (1-based index of the . in the string). The following returns multiple namespaces, but we show only first 3 in the output:

1: 
2: 
3: 
4: 
Http.RequestString
  ( "http://localhost:18083/completion", httpMethod="POST",
    body=TextRequest """{ "column":17,
      "sourceLine":"Microsoft.FSharp.Collections" }""")
[
  {
    "displayText": "Collections",
    "completionText": "Collections",
    "category": "",
    "icon": "Namespace",
    "overloads": [],
    "description": null
  },
  {
    "displayText": "Compiler",
    "completionText": "Compiler",
    "category": "",
    "icon": "Namespace",
    "overloads": [],
    "description": null
  },
  {
    "displayText": "Control",
    "completionText": "Control",
    "category": "",
    "icon": "Namespace",
    "overloads": [],
    "description": null
  }
]

Getting completion on previous symbols

The /completion command also works on symbols defined in previous interactions. For example, we can call /eval to evaluate let nums = [| 1 .. 10 |] and then get completion on the nums. value:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
Http.RequestString
  ( "http://localhost:18083/eval", httpMethod="POST",
    body=TextRequest """{ "file":"/a.fsx", "line":10,
      "code":"let nums = [| 1 .. 10 |]"}""")

Http.RequestString
  ( "http://localhost:18083/completion", httpMethod="POST",
    body=TextRequest """{ "column":5, "sourceLine":"nums.L" }""")
[
  {
    "displayText": "Clone",
    "completionText": "Clone",
    "category": "",
    "icon": "Method",
    "overloads": [],
    "description": null
  },
  {
    "displayText": "CopyTo",
    "completionText": "CopyTo",
    "category": "",
    "icon": "Method",
    "overloads": [],
    "description": null
  },
  {
    "displayText": "Equals",
    "completionText": "Equals",
    "category": "",
    "icon": "Method",
    "overloads": [],
    "description": null
  }
]

We only show the first 3 elements of the response here, but you can see that it contains methods that are only available on array object - in particular, the CopyTo and Clone methods come from array (while Equals comes from System.Object).

Getting tooltips in completion list

After you call /completion, the FsInteractiveService process remembers the symbols that it provided and it lets you get additional tool tip information for individual symbols in the list. For example, the following performs auto-completion on List. and then it looks for detailed information about the map function:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
Http.RequestString
  ( "http://localhost:18083/completion", httpMethod="POST",
    body=TextRequest """{ "column":5, "sourceLine":"List." }""")

Http.RequestString
  ( "http://localhost:18083/tooltip", httpMethod="POST",
    body=TextRequest """{ "filter":"map" }""")
{
  "signature": "val map :\n   mapping: 'T -> 'U ->\n   list   : 'T l...",
  "doc": {
    "key": "M:Microsoft.FSharp.Collections.ListModule.Map``2(M...",
    "fileName": "c:\\Tomas\\Public\\ionide\\FsInteractiveService\\bin\\Fs..."
  },
  "footer": "<small>Assembly:\tFSharp.Core</small>"
}

The value passed to the filter parameter has to be a full name of one of the items in the previously returned completion list. If the item is not found, the result is a JSON value null.

In the above response, the doc field returns a record with key and fileName that can be used to lookup the documentation. This may also be null or a field containing the inline XML documentation. To show the last case, the following defines a function hiThere with a /// documentation comment, finds it in completion list and gets its tooltip:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
Http.RequestString
  ( "http://localhost:18083/eval", httpMethod="POST",
    body=TextRequest """{ "file":"/a.fsx", "line":10,
      "code":"/// Hi there!\nlet hiThere() = 1"}""")

Http.RequestString
  ( "http://localhost:18083/completion", httpMethod="POST",
    body=TextRequest """{ "column":1, "sourceLine":"hi" }""")

Http.RequestString
  ( "http://localhost:18083/tooltip", httpMethod="POST",
    body=TextRequest """{ "filter":"hiThere" }""")
{
  "signature": "val hiThere :\n   : unit \n   -> int",
  "doc": {
    "xmldoc": " Hi there!"
  },
  "footer": "<small>Assembly:\tFSI-ASSEMBLY</small>"
}

Getting parameter hints

The /paramhints is the last command provided by the service. It returns information about method overloads. This can be used to show a tool tip when typing, for example, Console.WriteLine(. This is exactly what the following snippet shows. Here, the column value is a 1-based index of the opening parenthesis:

1: 
2: 
3: 
4: 
Http.RequestString
  ( "http://localhost:18083/paramhints", httpMethod="POST",
    body=TextRequest """{ "column":25,
      "sourceLine":"System.Console.WriteLine(123)" }""")
[
  {
    "signature": "static member WriteLine () : unit",
    "doc": {
      "key": "M:System.Console.WriteLine",
      "fileName": "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\ms..."
    },
    "parameters": []
  },
  {
    "signature": "static member WriteLine :\n   value: string \n      ...",
    "doc": {
      "key": "M:System.Console.WriteLine(System.String)",
      "fileName": "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\ms..."
    },
    "parameters": [
      "value"
    ]
  },
  {
    "signature": "static member WriteLine :\n   value: obj \n       ->...",
    "doc": {
      "key": "M:System.Console.WriteLine(System.Object)",
      "fileName": "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\ms..."
    },
    "parameters": [
      "value"
    ]
  }
]
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
namespace System
namespace System.Diagnostics
val root : string

Full name: Intelli.root
val fsiservice : Process

Full name: Intelli.fsiservice
Multiple items
type ProcessStartInfo =
  new : unit -> ProcessStartInfo + 2 overloads
  member Arguments : string with get, set
  member CreateNoWindow : bool with get, set
  member Domain : string with get, set
  member EnvironmentVariables : StringDictionary
  member ErrorDialog : bool with get, set
  member ErrorDialogParentHandle : nativeint with get, set
  member FileName : string with get, set
  member LoadUserProfile : bool with get, set
  member Password : SecureString with get, set
  ...

Full name: System.Diagnostics.ProcessStartInfo

--------------------
ProcessStartInfo() : unit
ProcessStartInfo(fileName: string) : unit
ProcessStartInfo(fileName: string, arguments: string) : unit
Multiple items
type Process =
  inherit Component
  new : unit -> Process
  member BasePriority : int
  member BeginErrorReadLine : unit -> unit
  member BeginOutputReadLine : unit -> unit
  member CancelErrorRead : unit -> unit
  member CancelOutputRead : unit -> unit
  member Close : unit -> unit
  member CloseMainWindow : unit -> bool
  member EnableRaisingEvents : bool with get, set
  member ExitCode : int
  ...

Full name: System.Diagnostics.Process

--------------------
Process() : unit
Process.Start(startInfo: ProcessStartInfo) : Process
Process.Start(fileName: string) : Process
Process.Start(fileName: string, arguments: string) : Process
Process.Start(fileName: string, userName: string, password: System.Security.SecureString, domain: string) : Process
Process.Start(fileName: string, arguments: string, userName: string, password: System.Security.SecureString, domain: string) : Process
type Http =
  private new : unit -> Http
  static member private AppendQueryToUrl : url:string * query:(string * string) list -> string
  static member AsyncRequest : url:string * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:CookieContainer * ?silentHttpErrors:bool * ?responseEncodingOverride:string * ?customizeHttpRequest:(HttpWebRequest -> HttpWebRequest) -> Async<HttpResponse>
  static member AsyncRequestStream : url:string * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:CookieContainer * ?silentHttpErrors:bool * ?customizeHttpRequest:(HttpWebRequest -> HttpWebRequest) -> Async<HttpResponseWithStream>
  static member AsyncRequestString : url:string * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:CookieContainer * ?silentHttpErrors:bool * ?responseEncodingOverride:string * ?customizeHttpRequest:(HttpWebRequest -> HttpWebRequest) -> Async<string>
  static member private InnerRequest : url:string * toHttpResponse:(string -> int -> string -> string -> string -> 'a0 option -> Map<string,string> -> Map<string,string> -> Stream -> Async<'a1>) * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:CookieContainer * ?silentHttpErrors:bool * ?responseEncodingOverride:'a0 * ?customizeHttpRequest:(HttpWebRequest -> HttpWebRequest) -> Async<'a1>
  static member Request : url:string * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:CookieContainer * ?silentHttpErrors:bool * ?responseEncodingOverride:string * ?customizeHttpRequest:(HttpWebRequest -> HttpWebRequest) -> HttpResponse
  static member RequestStream : url:string * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:CookieContainer * ?silentHttpErrors:bool * ?customizeHttpRequest:(HttpWebRequest -> HttpWebRequest) -> HttpResponseWithStream
  static member RequestString : url:string * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:CookieContainer * ?silentHttpErrors:bool * ?responseEncodingOverride:string * ?customizeHttpRequest:(HttpWebRequest -> HttpWebRequest) -> string

Full name: FSharp.Data.Http
static member Http.RequestString : url:string * ?query:(string * string) list * ?headers:seq<string * string> * ?httpMethod:string * ?body:HttpRequestBody * ?cookies:seq<string * string> * ?cookieContainer:System.Net.CookieContainer * ?silentHttpErrors:bool * ?responseEncodingOverride:string * ?customizeHttpRequest:(System.Net.HttpWebRequest -> System.Net.HttpWebRequest) -> string
union case HttpRequestBody.TextRequest: string -> HttpRequestBody
Process.Kill() : unit
F# Project
Fork me on GitHub