├── Icon512.png ├── .gitignore ├── syntaxes ├── README.md ├── fsharp.fsi.json ├── fsharp.fsl.json ├── fsharp.fsy.json ├── fsharp.fsx.json ├── fsharp.configuration.json ├── LICENSE.md └── fsharp.json ├── update.sh ├── pack.sh ├── update.ps1 ├── TODO.md ├── pack.ps1 ├── tsconfig.json ├── azure-pipelines.yml ├── .circleci └── config.yml ├── client ├── extension.ts ├── help.ts ├── repl.ts ├── protocol.ts └── fsac.ts ├── README.md ├── LICENSE.md ├── config_sample └── fsharp_core │ └── coc-settings.json ├── CocSettings.md └── package.json /Icon512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coc-extensions/coc-fsharp/HEAD/Icon512.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | out/ 4 | packages/ 5 | node_modules/ 6 | Scratch.fsx 7 | Scratch.ts 8 | publish/ 9 | coc-fsharp-*.tgz 10 | .vs 11 | -------------------------------------------------------------------------------- /syntaxes/README.md: -------------------------------------------------------------------------------- 1 | From https://github.com/ionide/ionide-fsgrammar/tree/master/grammar and https://github.com/ionide/ionide-vscode-fsharp/blob/master/release/language-configuration.json -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | pkill node 2 | npm run compile 3 | cp ./package.json ~/.config/coc/extensions/node_modules/coc-fsharp/package.json 4 | cp ./out/client/* ~/.config/coc/extensions/node_modules/coc-fsharp/out/client/ 5 | -------------------------------------------------------------------------------- /pack.sh: -------------------------------------------------------------------------------- 1 | # !/bin/bash 2 | plat="win10-x64 linux-x64 osx.10.11-x64" 3 | 4 | rm -rf ./bin 5 | rm -rf ./out 6 | rm -rf ./publish 7 | 8 | npm install 9 | npm run compile 10 | npm pack 11 | 12 | mkdir -p ./publish 13 | mkdir -p ./bin 14 | mv *.tgz ./publish/ 15 | 16 | -------------------------------------------------------------------------------- /update.ps1: -------------------------------------------------------------------------------- 1 | # Get-Process node | Stop-Process 2 | npm run compile 3 | Copy-Item -Force .\package.json ~\AppData\Local\coc\extensions\node_modules\coc-fsharp\package.json 4 | Copy-Item -Force .\out\client\* ~\AppData\Local\coc\extensions\node_modules\coc-fsharp\out\client\ 5 | -------------------------------------------------------------------------------- /syntaxes/fsharp.fsi.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fsharp.fsi", 3 | "scopeName": "source.fsharp.fsi", 4 | "fileTypes": [ 5 | "fsi" 6 | ], 7 | "foldingStartMarker": "", 8 | "foldingStopMarker": "", 9 | "patterns": [ 10 | { 11 | "include": "source.fsharp" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /syntaxes/fsharp.fsl.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fsharp.fsl", 3 | "scopeName": "source.fsharp.fsl", 4 | "fileTypes": [ 5 | "fsl" 6 | ], 7 | "foldingStartMarker": "", 8 | "foldingStopMarker": "", 9 | "patterns": [ 10 | { 11 | "include": "source.fsharp" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /syntaxes/fsharp.fsy.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fsharp.fsy", 3 | "scopeName": "source.fsharp.fsy", 4 | "fileTypes": [ 5 | "fsy" 6 | ], 7 | "foldingStartMarker": "", 8 | "foldingStopMarker": "", 9 | "patterns": [ 10 | { 11 | "include": "source.fsharp" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | Missing option: 2 | ``` 3 | "FSharp.dotNetRoot": { 4 | "scope": "application", 5 | "type": "bool", 6 | "default": true, 7 | "description": "sets the root path for finding dotnet SDK references. Primarily used for FSX Scripts. Default value: operating-system dependent. On windows, C:\Program Files\dotnet; on Unix, /usr/local/share/dotnet" 8 | }, 9 | ``` 10 | -------------------------------------------------------------------------------- /pack.ps1: -------------------------------------------------------------------------------- 1 | Stop-Process -Name 7zFM 2 | New-Item -ItemType Directory -Force -Name out 3 | New-Item -ItemType Directory -Force -Name publish 4 | New-Item -ItemType Directory -Force -Name bin 5 | Remove-Item bin/* -Recurse -Force 6 | Remove-Item out/* -Recurse -Force 7 | Remove-Item publish/* -Recurse -Force 8 | 9 | # client 10 | 11 | npm install 12 | npm run compile 13 | npm pack --silent 14 | Move-Item *.tgz publish/ 15 | 16 | -------------------------------------------------------------------------------- /syntaxes/fsharp.fsx.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fsharp.fsx", 3 | "scopeName": "source.fsharp.fsx", 4 | "fileTypes": [ 5 | "fsx" 6 | ], 7 | "foldingStartMarker": "", 8 | "foldingStopMarker": "", 9 | "patterns": [ 10 | { 11 | "include": "source.fsharp" 12 | }, 13 | { 14 | "name": "preprocessor.source.fsharp.fsx", 15 | "match": "^#(load|r|I|time)" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noUnusedLocals": false, 4 | "noUnusedParameters": false, 5 | "noImplicitAny": false, 6 | "noImplicitReturns": true, 7 | "target": "es6", 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "rootDir": ".", 11 | "outDir": "out", 12 | "lib": [ "es2016" ], 13 | "sourceMap": true, 14 | "allowSyntheticDefaultImports": true, 15 | "esModuleInterop": true 16 | }, 17 | "exclude": [ 18 | "node_modules", 19 | "server", 20 | "Scratch.ts" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Starter pipeline 2 | # Start with a minimal pipeline that you can customize to build and deploy your code. 3 | # Add steps that build, run tests, deploy, and more: 4 | # https://aka.ms/yaml 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'ubuntu-latest' 11 | steps: 12 | - task: UseDotNet@2 13 | displayName: 'Use .NET Core sdk' 14 | inputs: 15 | packageType: 'sdk' 16 | version: '3.1.x' 17 | includePreviewVersions: true 18 | - task: PowerShell@2 19 | inputs: 20 | filePath: 'pack.ps1' 21 | - task: PublishBuildArtifacts@1 22 | inputs: 23 | PathtoPublish: 'publish' 24 | ArtifactName: 'drop' 25 | publishLocation: 'Container' 26 | 27 | 28 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: microsoft/dotnet:2-sdk 6 | 7 | steps: 8 | - checkout 9 | - run: 10 | name: Restore test projects 11 | command: bash scripts/restore.sh 12 | - run: 13 | name: Build all 14 | command: dotnet build 15 | - run: 16 | name: Test LSP.Tests 17 | command: dotnet test tests/LSP.Tests 18 | - run: 19 | name: Test ProjectCracker.Tests 20 | command: dotnet test tests/ProjectCracker.Tests 21 | - run: 22 | name: Test FSharpLanguageServer.Tests 23 | command: dotnet test tests/FSharpLanguageServer.Tests 24 | -------------------------------------------------------------------------------- /client/extension.ts: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | * ------------------------------------------------------------------------------------------ */ 5 | 'use strict'; 6 | 7 | import {workspace, ExtensionContext, commands} from 'coc.nvim'; 8 | import FSAC from './fsac'; 9 | import Help from './help'; 10 | import Repl from './repl'; 11 | import {sleep} from 'coc-utils'; 12 | 13 | export async function activate(context: ExtensionContext) { 14 | 15 | await FSAC.activate(context); 16 | await Help.activate(context); 17 | await Repl.activate(context); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /client/help.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import {ExtensionContext, commands, workspace, Uri, window} from "coc.nvim"; 4 | import FSAC from "./fsac"; 5 | 6 | export default class Help { 7 | 8 | private static async getHelp() { 9 | var helpKey = await FSAC.f1help(); 10 | if (helpKey == null) {return;} 11 | helpKey = helpKey.replace("#ctor", "-ctor").replace('`','-'); 12 | let uri = Uri.parse (`https://docs.microsoft.com/en-us/dotnet/api/${helpKey}`); 13 | workspace.openResource(uri.toString()); 14 | } 15 | 16 | public static async activate(context: ExtensionContext) { 17 | // Register commands 18 | context.subscriptions.push( 19 | commands.registerCommand('fsharp.fsdn', async () => { 20 | window.showMessage("Not implemented...", "error"); 21 | }), 22 | commands.registerCommand('fsharp.f1Help', this.getHelp), 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # coc-fsharp: F# Language Server for coc.nvim 2 | 3 | This project is a language server extension for coc.nvim. 4 | 5 | Originally, this project started from [another F# language server](https://github.com/fsprojects/fsharp-language-server) but I find it hard to keep up with the changes. Now this project is essentially a thin wrapper around [FSAutoComplete](https://github.com/fsharp/fsautocomplete). 6 | 7 | # Installation 8 | - You'll need [coc.nvim](https://github.com/neoclide/coc.nvim) installed first. 9 | - Check `:set ft=` and if the result is not "fsharp", it doesn't trigger plugin initialization. Use something like https://github.com/sheerun/vim-polyglot 10 | - Run `:CocInstall coc-fsharp` 11 | 12 | # Troubleshooting 13 | - Feel free to open issues if you have problems. 14 | - The more information I have, the better I diagnose. 15 | - Usually I'll need: 16 | - `:CocInfo` 17 | - ~~`project_root/obj/project.assets.json`~~ 18 | - Problems related to FSAC will not be supported here. 19 | -------------------------------------------------------------------------------- /syntaxes/fsharp.configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "comments": { 4 | "lineComment": "//", 5 | "blockComment": [ "(*", "*)" ] 6 | }, 7 | 8 | "autoClosingPairs": [ 9 | ["[", "]"], 10 | ["(", ")"], 11 | ["{", "}"], 12 | ["<@", "@>"], 13 | ["``", "``"], 14 | ["\"", "\""], 15 | ["(|", "|)"], 16 | ["[<",">]"], 17 | ["[|", "|]"], 18 | ["(*", "*)" ], 19 | ["<@@", "@@>"] 20 | ], 21 | 22 | "surroundingPairs": [ 23 | ["<@@", "@@>"], 24 | ["(|", "|)"], 25 | ["[<",">]"], 26 | ["[|", "|]"], 27 | ["{", "}"], 28 | ["[", "]"], 29 | ["(", ")"], 30 | ["\"", "\""], 31 | ["\"\"\"", "\"\"\""], 32 | ["(*", "*)"], 33 | ["<@", "@>"], 34 | ["'", "'"] 35 | ], 36 | 37 | "brackets": [ 38 | ["(", ")"], 39 | ["(*", "*)"], 40 | ["{", "}"], 41 | ["[", "]"], 42 | ["[|", "|]"], 43 | ["<@", "@>"], 44 | ["<@@", "@@>"] 45 | ], 46 | 47 | "wordPattern": "((\\w*')(\\w'?)*)|(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\\/\\s]+)" 48 | 49 | } 50 | -------------------------------------------------------------------------------- /syntaxes/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Krzysztof Cieslak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) [F# Language Server Contributors](https://github.com/fsprojects/fsharp-language-server/graphs/contributors) 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | ----- 25 | 26 | The contents of the spacemacs directory are derived from the fsharp layer in [Spacemacs](https://github.com/syl20bnr/spacemacs), and are licensed under the GPLv3. 27 | -------------------------------------------------------------------------------- /client/repl.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import {ExtensionContext, commands, workspace} from "coc.nvim"; 4 | import {REPLProvider} from "coc-utils"; 5 | 6 | export default class Repl { 7 | 8 | private static registerREPL(context: ExtensionContext, title: string) { 9 | 10 | let replProvider = new REPLProvider({ 11 | title: title, 12 | command: "dotnet", 13 | args: ['fsi', '--readline+', '--utf8output', '--nologo'], 14 | commit: ';;', 15 | filetype: 'fsharp' 16 | }) 17 | 18 | let cmdEvalLine = commands.registerCommand("fsharp.evaluateLine", async () => await replProvider.eval('n')); 19 | let cmdEvalSelection = commands.registerCommand("fsharp.evaluateSelection", async () => await replProvider.eval('v')); 20 | let cmdExecFile = commands.registerCommand("fsharp.run", async (...args: any[]) => { 21 | let root = workspace.rootPath 22 | 23 | let argStrs = args 24 | ? args.map(x => `${x}`) 25 | : [] 26 | 27 | let term = await workspace.createTerminal({ 28 | name: `FSI`, 29 | shellPath: "dotnet", 30 | cwd: root, 31 | shellArgs: ['run'].concat(argStrs) 32 | }) 33 | 34 | // switch to the terminal and steal focus 35 | term.show(false) 36 | }) 37 | 38 | // Push the disposable to the context's subscriptions so that the 39 | // client can be deactivated on extension deactivation 40 | // TODO push the repl provider 41 | context.subscriptions.push(cmdExecFile, cmdEvalLine, cmdEvalSelection); 42 | } 43 | 44 | public static async activate(context: ExtensionContext) { 45 | this.registerREPL(context, "FSI"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /client/protocol.ts: -------------------------------------------------------------------------------- 1 | import {RequestType} from 'vscode-languageserver-protocol' 2 | 3 | export interface WorkspacePeekParams { 4 | Directory: string, 5 | Deep: number, 6 | ExcludedDirs: string[] 7 | } 8 | 9 | /* 10 | [workspacePeek] 11 | {"Kind":"workspacePeek","Data":{"Found": [{"Type":"solution","Data":{"Path":"E:\\git\\fvim\\fvim.sln","Items":[{"Guid":"e6eae040-4432-434a-8363-bd76b1974ef4","Name":"E:\\git\\fvim\\fvim.fsproj","Kind":{"Kind":"msbuildFormat","Data":{"Configurations":[]}}}],"Configurations":[]}}, {"Type":"directory","Data":{"Directory":"E:\\git\\fvim","Fsprojs":["E:\\git\\fvim\\Avalonia\\fvim_avalonia.fsproj","E:\\git\\fvim\\fvim.fsproj"]}}]}} 12 | let str = '{"Kind":"workspacePeek","Data":{"Found": [{"Type":"solution","Data":{"Path":"asdfasdf","Items":[{"Guid":"e6eae040-4432-434a-8363-bd76b1974ef4","Name":"asdfasdf","Kind":{"Kind":"msbuildFormat","Data":{"Configurations":[]}}}],"Configurations":[]}}, {"Type":"directory","Data":{"Directory":"asdfasdf","Fsprojs":["asdfasdf","asdfasdf"]}}]}}' 13 | */ 14 | 15 | export interface ProjectItem { 16 | Guid: string, 17 | Name: string, 18 | Kind: { 19 | Kind: "msbuildFormat", 20 | Data: { 21 | Configurations: [string] 22 | } 23 | } 24 | } 25 | 26 | export interface WorkspaceSolution { 27 | Type: "solution", 28 | Data: { 29 | Path: string, 30 | Items: [ProjectItem] 31 | } 32 | } 33 | 34 | export interface WorkspaceDirectory { 35 | Type: "directory", 36 | Data: { 37 | Directory: string, 38 | Fsprojs: [string] 39 | } 40 | } 41 | 42 | export interface WorkspacePeekResponse { 43 | Kind: "workspacePeek", 44 | Data: { 45 | Found: [WorkspaceSolution | WorkspaceDirectory] 46 | } 47 | } 48 | 49 | export interface FSACResponse { 50 | content: string 51 | } 52 | 53 | export namespace WorkspacePeekRequest { 54 | export const type = new RequestType("fsharp/workspacePeek") 55 | } 56 | -------------------------------------------------------------------------------- /config_sample/fsharp_core/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "fsharp.codelens.references": false, 3 | "fsharp.project.otherFlags": [ 4 | "--warnon:1182", 5 | "--compiling-fslib", 6 | "--compiling-fslib-40", 7 | "--maxerrors:20", 8 | "--extraoptimizationloops:1", 9 | "--tailcalls+", 10 | "--deterministic+", 11 | "--target:library", 12 | "--fullpaths", 13 | "--flaterrors", 14 | "--highentropyva+", 15 | "--targetprofile:netcore", 16 | "--simpleresolution", 17 | "-g", 18 | "--debug:portable", 19 | "--noframework", 20 | "--define:TRACE", 21 | "--define:FSHARP_CORE", 22 | "--define:DEBUG", 23 | "--define:NETSTANDARD", 24 | "--define:FX_NO_APP_DOMAINS", 25 | "--define:FX_NO_ARRAY_LONG_LENGTH", 26 | "--define:FX_NO_BEGINEND_READWRITE", 27 | "--define:FX_NO_BINARY_SERIALIZATION", 28 | "--define:FX_NO_CONVERTER", 29 | "--define:FX_NO_DEFAULT_DEPENDENCY_TYPE", 30 | "--define:FX_NO_CORHOST_SIGNER", 31 | "--define:FX_NO_EVENTWAITHANDLE_IDISPOSABLE", 32 | "--define:FX_NO_EXIT_CONTEXT_FLAGS", 33 | "--define:FX_NO_LINKEDRESOURCES", 34 | "--define:FX_NO_PARAMETERIZED_THREAD_START", 35 | "--define:FX_NO_PDB_READER", 36 | "--define:FX_NO_PDB_WRITER", 37 | "--define:FX_NO_REFLECTION_MODULE_HANDLES", 38 | "--define:FX_NO_REFLECTION_ONLY", 39 | "--define:FX_NO_RUNTIMEENVIRONMENT", 40 | "--define:FX_NO_SECURITY_PERMISSIONS", 41 | "--define:FX_NO_SERVERCODEPAGES", 42 | "--define:FX_NO_SYMBOLSTORE", 43 | "--define:FX_NO_SYSTEM_CONFIGURATION", 44 | "--define:FX_NO_THREAD", 45 | "--define:FX_NO_THREADABORT", 46 | "--define:FX_NO_WAITONE_MILLISECONDS", 47 | "--define:FX_NO_WEB_CLIENT", 48 | "--define:FX_NO_WIN_REGISTRY", 49 | "--define:FX_NO_WINFORMS", 50 | "--define:FX_NO_INDENTED_TEXT_WRITER", 51 | "--define:FX_REDUCED_EXCEPTIONS", 52 | "--define:FX_RESHAPED_REFEMIT", 53 | "--define:FX_RESHAPED_GLOBALIZATION", 54 | "--define:FX_RESHAPED_REFLECTION", 55 | "--define:FX_RESHAPED_MSBUILD", 56 | "--define:NETSTANDARD", 57 | "--define:NETSTANDARD1_6", 58 | //"--keyfile:C:\Users\Yatao\.nuget\packages\microsoft.dotnet.arcade.sdk\1.0.0-beta.19264.13\tools\snk/MSFT.snk 59 | //"--publicsign+ 60 | "--optimize-", 61 | //"--resource:C:\Users\Yatao\git\visualfsharp\artifacts\obj\FSharp.Core\Debug\netstandard1.6\FSCore.resources 62 | ], 63 | "fsharp.project.includeCompileBefore": true 64 | } 65 | -------------------------------------------------------------------------------- /CocSettings.md: -------------------------------------------------------------------------------- 1 | coc.nvim settings 2 | ----------------- 3 | 4 | We can specify project-wide settings by creating `.vim/coc-settings.json` in the project directory. 5 | 6 | 7 | ## Setting build parameters 8 | 9 | The default project cracker may not infer the correct build parameters (MSBuild properties, fsc flags, etc). 10 | To circumvent this problem, alter `fsharp.project.define` and `fsharp.project.otherflags` . 11 | The former is a simple array of conditional compilation flags passed to MSBuild. 12 | The latter is lower-level, and consists of flags passed directly to the F# compiler `fsc`. 13 | The best way to find out the compile parameters is to actually build the project with Visual Studio or `dotnet` command line. 14 | Setting the build output verbosity to `normal` or above, and the `fsc` compiler flags will be displayed. 15 | For example, to get the F# core library project, `FSharp.Core.fsproj` to typecheck, we will need the following configuration: 16 | 17 | ```json 18 | { 19 | "fsharp.codelens.references": false, 20 | "fsharp.project.otherFlags": [ 21 | "--warnon:1182", 22 | "--compiling-fslib", 23 | "--compiling-fslib-40", 24 | "--maxerrors:20", 25 | "--extraoptimizationloops:1", 26 | "--tailcalls+", 27 | "--deterministic+", 28 | "--target:library", 29 | "--fullpaths", 30 | "--flaterrors", 31 | "--highentropyva+", 32 | "--targetprofile:netcore", 33 | "--simpleresolution", 34 | "-g", 35 | "--debug:portable", 36 | "--noframework", 37 | "--define:TRACE", 38 | "--define:FSHARP_CORE", 39 | "--define:DEBUG", 40 | "--define:NETSTANDARD", 41 | "--define:FX_NO_APP_DOMAINS", 42 | "--define:FX_NO_ARRAY_LONG_LENGTH", 43 | "--define:FX_NO_BEGINEND_READWRITE", 44 | "--define:FX_NO_BINARY_SERIALIZATION", 45 | "--define:FX_NO_CONVERTER", 46 | "--define:FX_NO_DEFAULT_DEPENDENCY_TYPE", 47 | "--define:FX_NO_CORHOST_SIGNER", 48 | "--define:FX_NO_EVENTWAITHANDLE_IDISPOSABLE", 49 | "--define:FX_NO_EXIT_CONTEXT_FLAGS", 50 | "--define:FX_NO_LINKEDRESOURCES", 51 | "--define:FX_NO_PARAMETERIZED_THREAD_START", 52 | "--define:FX_NO_PDB_READER", 53 | "--define:FX_NO_PDB_WRITER", 54 | "--define:FX_NO_REFLECTION_MODULE_HANDLES", 55 | "--define:FX_NO_REFLECTION_ONLY", 56 | "--define:FX_NO_RUNTIMEENVIRONMENT", 57 | "--define:FX_NO_SECURITY_PERMISSIONS", 58 | "--define:FX_NO_SERVERCODEPAGES", 59 | "--define:FX_NO_SYMBOLSTORE", 60 | "--define:FX_NO_SYSTEM_CONFIGURATION", 61 | "--define:FX_NO_THREAD", 62 | "--define:FX_NO_THREADABORT", 63 | "--define:FX_NO_WAITONE_MILLISECONDS", 64 | "--define:FX_NO_WEB_CLIENT", 65 | "--define:FX_NO_WIN_REGISTRY", 66 | "--define:FX_NO_WINFORMS", 67 | "--define:FX_NO_INDENTED_TEXT_WRITER", 68 | "--define:FX_REDUCED_EXCEPTIONS", 69 | "--define:FX_RESHAPED_REFEMIT", 70 | "--define:FX_RESHAPED_GLOBALIZATION", 71 | "--define:FX_RESHAPED_REFLECTION", 72 | "--define:FX_RESHAPED_MSBUILD", 73 | "--define:NETSTANDARD", 74 | "--define:NETSTANDARD1_6", 75 | "--optimize-" 76 | ], 77 | "fsharp.project.includeCompileBefore": true 78 | } 79 | ``` 80 | 81 | ## Working with FSLex/FSYacc 82 | 83 | Set `fsharp.project.includeCompileBefore` so that the lexer/parser can access the `` MSBuild items. 84 | 85 | -------------------------------------------------------------------------------- /client/fsac.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import {ExtensionContext, ServerOptions, TransportKind, LanguageClientOptions, workspace, window, LanguageClient, commands, Disposable, CloseAction, ErrorAction, RevealOutputChannelOn, Uri} from "coc.nvim"; 4 | import {ILanguageServerPackages, LanguageServerRepository, LanguageServerProvider, sleep, DotnetResolver} from "coc-utils"; 5 | import {TextDocumentIdentifier, Message} from "vscode-languageserver-protocol"; 6 | import path from 'path' 7 | import {WorkspacePeekRequest, WorkspacePeekParams, FSACResponse, WorkspacePeekResponse, WorkspaceSolution, WorkspaceDirectory} from './protocol' 8 | 9 | const fsac_pkgs: ILanguageServerPackages = { 10 | "win-x64": { 11 | executable: "tools/net6.0/any/fsautocomplete.dll", 12 | platformPath: /fsautocomplete\..*\.nupkg/ 13 | }, 14 | "linux-x64": { 15 | executable: "tools/net6.0/any/fsautocomplete.dll", 16 | platformPath: /fsautocomplete\..*\.nupkg/ 17 | }, 18 | "osx-x64": { 19 | executable: "tools/net6.0/any/fsautocomplete.dll", 20 | platformPath: /fsautocomplete\..*\.nupkg/ 21 | }, 22 | "osx-arm64": { 23 | executable: "tools/net6.0/any/fsautocomplete.dll", 24 | platformPath: /fsautocomplete\..*\.nupkg/ 25 | }, 26 | "linux-arm64": { 27 | executable: "tools/net6.0/any/fsautocomplete.dll", 28 | platformPath: /fsautocomplete\..*\.nupkg/ 29 | }, 30 | } 31 | 32 | const fsac_repo: LanguageServerRepository = { 33 | kind: "github", 34 | repo: "fsharp/FsAutoComplete", 35 | channel: "latest" 36 | } 37 | 38 | 39 | export default class FSAC { 40 | private static client: LanguageClient; 41 | private static clientDisposable: Disposable; 42 | 43 | public static async f1help(): Promise { 44 | if (!FSAC.client.started) { 45 | return null; 46 | } 47 | let cursor = await window.getCursorPosition(); 48 | let doc = await workspace.document; 49 | let id = TextDocumentIdentifier.create(doc.uri); 50 | let uri = await FSAC.client.sendRequest('fsharp/f1Help', { 51 | textDocument: id, 52 | position: cursor 53 | }); 54 | return JSON.parse(uri.content).Data; 55 | } 56 | 57 | public static async activate(context: ExtensionContext) { 58 | // The server is packaged as a .NET core assembly 59 | const lsprovider = new LanguageServerProvider(context, "FSAC server", fsac_pkgs, fsac_repo) 60 | const languageServerExe = await lsprovider.getLanguageServer() 61 | const config = workspace.getConfiguration('FSharp') 62 | let verbose = false; 63 | let statePath = path.join(workspace.cwd, ".coc-fsharp") 64 | let serverArgs = [languageServerExe, "--background-service-enabled", "--state-directory", statePath] 65 | 66 | if (config.get("server.trace")) { 67 | serverArgs.push("--verbose") 68 | context.logger.info("coc-fsharp: activating verbose logging") 69 | verbose = true; 70 | } 71 | 72 | let autoInit = config.get("AutomaticWorkspaceInit", true) 73 | let dotnet = await DotnetResolver.getDotnetInfo() 74 | let dotnetRoot = path.join(dotnet.sdksInstalled[0].path, '..') 75 | 76 | config.update("AutomaticWorkspaceInit", autoInit) 77 | 78 | let env = Object.assign(process.env, {DOTNET_ROOT: dotnetRoot}) 79 | let serverOptions: ServerOptions = { 80 | command: "dotnet", 81 | args: serverArgs, 82 | options: { env: env, cwd: workspace.cwd }, 83 | transport: TransportKind.stdio 84 | } 85 | 86 | let server_outputchannel = window.createOutputChannel("FSAC") 87 | if (verbose) { 88 | server_outputchannel.show() 89 | } 90 | 91 | // Options to control the language client 92 | let clientOptions: LanguageClientOptions = { 93 | // Register the server for F# documents 94 | documentSelector: [{scheme: 'file', language: 'fsharp'}], 95 | synchronize: { 96 | // Synchronize the setting section 'FSharp' to the server 97 | configurationSection: 'FSharp', 98 | // Notify the server about file changes to F# project files contain in the workspace 99 | fileEvents: [ 100 | workspace.createFileSystemWatcher('**/*.fsproj'), 101 | workspace.createFileSystemWatcher('**/*.fs'), 102 | workspace.createFileSystemWatcher('**/*.fsi'), 103 | workspace.createFileSystemWatcher('**/*.fsx'), 104 | workspace.createFileSystemWatcher('**/project.assets.json') 105 | ], 106 | }, 107 | initializationOptions: { 108 | // setting it to true will start Workspace Loading without need to run fsharp/workspacePeek and fsharp/workspaceLoad commands. 109 | // It will always choose top workspace from the found list - all projects in workspace if 0 .sln files are found, .sln file 110 | // if 1 .sln file was found, .sln file with most projects if multiple .sln files were found. It's designed to be used in clients 111 | // that doesn't allow to create custom UI for selecting workspaces. 112 | AutomaticWorkspaceInit: autoInit 113 | }, 114 | outputChannel: server_outputchannel, 115 | } 116 | 117 | // Create the language client and start the client. 118 | FSAC.client = new LanguageClient('fsharp', 'FsAutoComplete Language Server', serverOptions, clientOptions); 119 | FSAC.clientDisposable = FSAC.client.start(); 120 | FSAC.client.onReady().then(() => { 121 | FSAC.client.onNotification("fsharp/notifyWorkspace", (p) => { 122 | let content = JSON.parse(p.content) 123 | server_outputchannel.appendLine(`[notifyWorkspace]: ${JSON.stringify(content)}`) 124 | }); 125 | }); 126 | 127 | // Push the disposable to the context's subscriptions so that the 128 | // client can be deactivated on extension deactivation 129 | context.subscriptions.push(FSAC.clientDisposable); 130 | context.subscriptions.push( 131 | commands.registerCommand('fsharp.downloadLanguageServer', async () => { 132 | if (FSAC.client.started) { 133 | await FSAC.client.stop() 134 | FSAC.clientDisposable.dispose() 135 | await sleep(1000) 136 | } 137 | await lsprovider.downloadLanguageServer(); 138 | FSAC.clientDisposable = FSAC.client.start() 139 | context.subscriptions.push(FSAC.clientDisposable); 140 | }), 141 | commands.registerCommand('fsharp.compile', async () => { 142 | window.showMessage("Not implemented...", "error"); 143 | //if (client.started) { 144 | //await client.sendRequest("fsharp/compile"); 145 | //} 146 | }), 147 | commands.registerCommand('fsharp.loadProject', async () => { 148 | let param: WorkspacePeekParams = { Directory: workspace.cwd, Deep: 2, ExcludedDirs: [] } 149 | let p = await FSAC.client.sendRequest("fsharp/workspacePeek", param) 150 | server_outputchannel.appendLine(p.content) 151 | let x = JSON.parse(p.content) as WorkspacePeekResponse 152 | let entryNames = x.Data.Found.map((v: WorkspaceSolution | WorkspaceDirectory) => { 153 | if (v.Type == "solution") { 154 | return `Solution: ${path.basename(v.Data.Path)}` 155 | } else { 156 | return `Directory: ${v.Data.Directory} (${v.Data.Fsprojs.length} projects)` 157 | } 158 | }) 159 | let items = await ( async () => { 160 | let selected = x.Data.Found[await window.showMenuPicker(entryNames, "F# Workspace Peek")] 161 | if (selected.Type == "solution") { 162 | return [TextDocumentIdentifier.create(Uri.file(selected.Data.Path).toString())] 163 | } else { 164 | return selected.Data.Fsprojs.map(v => TextDocumentIdentifier.create(Uri.file(v).toString())) 165 | } 166 | })() 167 | await FSAC.client.sendRequest("fsharp/workspaceLoad", {TextDocuments: items}) 168 | }), 169 | ); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coc-fsharp", 3 | "displayName": "F# Language Server for coc.nvim", 4 | "description": "F# Language Support using FSAC", 5 | "author": "Yatao Li", 6 | "license": "MIT", 7 | "icon": "Icon512.png", 8 | "version": "0.3.5", 9 | "publisher": "yatli", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/yatli/fsharp-language-server" 13 | }, 14 | "keywords": [ 15 | "fsharp", 16 | "coc.nvim", 17 | "dotnet", 18 | ".NET Core", 19 | ".NET" 20 | ], 21 | "categories": [ 22 | "Programming Languages", 23 | "Linters", 24 | "coc.nvim" 25 | ], 26 | "activationEvents": [ 27 | "onLanguage:fsharp" 28 | ], 29 | "main": "out/client/extension.js", 30 | "files": [ 31 | "out", 32 | "syntaxes" 33 | ], 34 | "contributes": { 35 | "languages": [ 36 | { 37 | "id": "fsharp", 38 | "aliases": [ 39 | "F#", 40 | "FSharp", 41 | "fsharp" 42 | ], 43 | "extensions": [ 44 | ".fs", 45 | ".fsx", 46 | ".fsi", 47 | ".fsl", 48 | ".fsy" 49 | ], 50 | "configuration": "syntaxes/fsharp.configuration.json" 51 | } 52 | ], 53 | "grammars": [ 54 | { 55 | "language": "fsharp", 56 | "scopeName": "source.fsharp", 57 | "path": "syntaxes/fsharp.json" 58 | }, 59 | { 60 | "language": "fsharp", 61 | "scopeName": "source.fsharp.fsx", 62 | "path": "syntaxes/fsharp.fsx.json" 63 | }, 64 | { 65 | "language": "fsharp", 66 | "scopeName": "source.fsharp.fsi", 67 | "path": "syntaxes/fsharp.fsi.json" 68 | } 69 | ], 70 | "configuration": { 71 | "type": "object", 72 | "title": "FSharp configuration", 73 | "properties": { 74 | "FSharp.AutomaticWorkspaceInit": { 75 | "scope": "application", 76 | "type": "boolean", 77 | "default": true, 78 | "description": "Automatically initialize workspace solution/project." 79 | }, 80 | "FSharp.server.trace": { 81 | "scope": "application", 82 | "type": "boolean", 83 | "default": false, 84 | "description": "Enables verbose log tracing." 85 | }, 86 | "FSharp.KeywordsAutocomplete": { 87 | "scope": "application", 88 | "type": "boolean", 89 | "default": false, 90 | "description": "provides keywords in autocomplete list" 91 | }, 92 | "FSharp.ExternalAutocomplete": { 93 | "scope": "application", 94 | "type": "boolean", 95 | "default": false, 96 | "description": "provides autocomplete for symbols from not opened namespaces/modules, insert open on accept, recommended default value: false" 97 | }, 98 | "FSharp.Linter": { 99 | "scope": "application", 100 | "type": "boolean", 101 | "default": true, 102 | "description": "enables FSharpLint integration, provides additional warnings and code action fixes, recommended default value: true" 103 | }, 104 | "FSharp.UnionCaseStubGeneration": { 105 | "scope": "application", 106 | "type": "boolean", 107 | "default": true, 108 | "description": "enables code action to generate pattern matching cases, recommended default value: true" 109 | }, 110 | "FSharp.UnionCaseStubGenerationBody": { 111 | "scope": "application", 112 | "type": "string", 113 | "default": "failwith \"Not Implemented\"", 114 | "description": "defines dummy body used by pattern matching generator, recommended default value: \"failwith \\\"Not Implemented\\\"\"" 115 | }, 116 | "FSharp.RecordStubGeneration": { 117 | "scope": "application", 118 | "type": "boolean", 119 | "default": true, 120 | "description": "enables code action to generate record stub, recommended default value: true" 121 | }, 122 | "FSharp.RecordStubGenerationBody": { 123 | "scope": "application", 124 | "type": "string", 125 | "default": "failwith \"Not Implemented\"", 126 | "description": "defines dummy body used by record stub generator, recommended default value: \"failwith \\\"Not Implemented\\\"\"" 127 | }, 128 | "FSharp.InterfaceStubGeneration": { 129 | "scope": "application", 130 | "type": "boolean", 131 | "default": true, 132 | "description": "enables code action to generate interface stub, recommended default value: true" 133 | }, 134 | "FSharp.InterfaceStubGenerationObjectIdentifier": { 135 | "scope": "application", 136 | "type": "string", 137 | "default": "this", 138 | "description": "defines object identifier used by interface stub generator,recommended default value: \"this\"" 139 | }, 140 | "FSharp.InterfaceStubGenerationMethodBody": { 141 | "scope": "application", 142 | "type": "string", 143 | "default": "failwith \"Not Implemented\"", 144 | "description": "defines dummy body used by interface stub generator, recommended default value: \"failwith \\\"Not Implemented\\\"\"" 145 | }, 146 | "FSharp.UnusedOpensAnalyzer": { 147 | "scope": "application", 148 | "type": "boolean", 149 | "default": true, 150 | "description": "enables unused open detections, recommended default value: true" 151 | }, 152 | "FSharp.UnusedDeclarationsAnalyzer": { 153 | "scope": "application", 154 | "type": "boolean", 155 | "default": true, 156 | "description": "enables unused symbol detection, recommended default value: true" 157 | }, 158 | "FSharp.UseSdkScripts": { 159 | "scope": "application", 160 | "type": "boolean", 161 | "default": true, 162 | "description": "enables the use of .Net Core SDKs for script file type-checking and evaluation, otherwise the .Net Framework reference lists will be used. Recommended default value: true." 163 | }, 164 | "FSharp.SimplifyNameAnalyzer": { 165 | "scope": "application", 166 | "type": "boolean", 167 | "default": false, 168 | "description": "enables simplify name analyzer and remove redundant qualifier quick fix, recommended default value: false" 169 | }, 170 | "FSharp.ResolveNamespaces": { 171 | "scope": "application", 172 | "type": "boolean", 173 | "default": true, 174 | "description": "enables resolve namespace quick fix (add open if symbol is from not yet opened module/namespace), recommended default value: true" 175 | }, 176 | "FSharp.EnableReferenceCodeLens": { 177 | "scope": "application", 178 | "type": "boolean", 179 | "default": true, 180 | "description": "enables reference count code lenses, recommended default value: true if --background-service-enabled is used by default, false otherwise" 181 | }, 182 | "FSharp.FSIExtraParameters": { 183 | "scope": "application", 184 | "type": "array", 185 | "default": [], 186 | "description": "an array of additional runtime arguments that are passed to FSI. These are used when typechecking scripts to ensure that typechecking has the same context as your FSI instances. An example would be to set the following parameters to enable Preview features (like opening static classes) for typechecking." 187 | } 188 | } 189 | }, 190 | "rootPatterns": [ 191 | { 192 | "filetype": "fsharp", 193 | "patterns": [ 194 | "*.fsproj", 195 | "*.sln", 196 | "*.fsx", 197 | "projects.assets.json", 198 | ".vim", 199 | ".git", 200 | ".hg" 201 | ] 202 | } 203 | ] 204 | }, 205 | "scripts": { 206 | "compile": "tsc -p ./", 207 | "watch": "tsc -watch -p ./" 208 | }, 209 | "extensionDependencies": [], 210 | "engines": { 211 | "coc": "^0.0.80" 212 | }, 213 | "dependencies": { 214 | "coc-utils": "0.0.17", 215 | "vscode-jsonrpc": ">=4.0.0", 216 | "vscode-languageserver-protocol": ">=3.14.0" 217 | }, 218 | "devDependencies": { 219 | "@types/follow-redirects": "^1.8.0", 220 | "typescript": "^4.6.2", 221 | "coc.nvim": "^0.0.80" 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /syntaxes/fsharp.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fsharp", 3 | "scopeName": "source.fsharp", 4 | "fileTypes": [ 5 | "fs" 6 | ], 7 | "foldingStartMarker": "", 8 | "foldingStopMarker": "", 9 | "patterns": [ 10 | { 11 | "include": "#compiler_directives" 12 | }, 13 | { 14 | "include": "#comments" 15 | }, 16 | { 17 | "include": "#constants" 18 | }, 19 | { 20 | "include": "#strings" 21 | }, 22 | { 23 | "include": "#chars" 24 | }, 25 | { 26 | "include": "#double_tick" 27 | }, 28 | { 29 | "include": "#definition" 30 | }, 31 | { 32 | "include": "#abstract_definition" 33 | }, 34 | { 35 | "include": "#attributes" 36 | }, 37 | { 38 | "include": "#modules" 39 | }, 40 | { 41 | "include": "#anonymous_functions" 42 | }, 43 | { 44 | "include": "#du_declaration" 45 | }, 46 | { 47 | "include": "#record_declaration" 48 | }, 49 | { 50 | "include": "#records" 51 | }, 52 | { 53 | "include": "#strp_inlined" 54 | }, 55 | { 56 | "include": "#keywords" 57 | }, 58 | { 59 | "include": "#cexprs" 60 | }, 61 | { 62 | "include": "#text" 63 | } 64 | ], 65 | "repository": { 66 | "strp_inlined_body": { 67 | "patterns": [ 68 | { 69 | "include": "#comments" 70 | }, 71 | { 72 | "include": "#anonymous_functions" 73 | }, 74 | { 75 | "match": "(\\^[[:alpha:]0-9'._]+)", 76 | "captures": { 77 | "1": { 78 | "name": "entity.name.type.fsharp" 79 | } 80 | } 81 | }, 82 | { 83 | "name": "keyword.fsharp", 84 | "match": "\\b(and|when|or)\\b" 85 | }, 86 | { 87 | "begin": "(\\()", 88 | "beginCaptures": { 89 | "1": { 90 | "name": "keyword.symbol.fsharp" 91 | } 92 | }, 93 | "end": "(\\))", 94 | "endCaptures": { 95 | "1": { 96 | "name": "keyword.symbol.fsharp" 97 | } 98 | }, 99 | "patterns": [ 100 | { 101 | "include": "#strp_inlined_body" 102 | } 103 | ] 104 | }, 105 | { 106 | "match": "(static member|member)\\s*([[:alpha:]0-9'`<>^._]+|``[[:alpha:]0-9' <>^._]+``)\\s*(:)", 107 | "captures": { 108 | "1": { 109 | "name": "keyword.fsharp" 110 | }, 111 | "2": { 112 | "name": "variable.fsharp" 113 | }, 114 | "3": { 115 | "name": "keyword.symbol.fsharp" 116 | } 117 | } 118 | }, 119 | { 120 | "include": "#compiler_directives" 121 | }, 122 | { 123 | "include": "#constants" 124 | }, 125 | { 126 | "include": "#strings" 127 | }, 128 | { 129 | "include": "#chars" 130 | }, 131 | { 132 | "include": "#double_tick" 133 | }, 134 | { 135 | "include": "#keywords" 136 | }, 137 | { 138 | "include": "#text" 139 | }, 140 | { 141 | "include": "#definition" 142 | }, 143 | { 144 | "include": "#attributes" 145 | }, 146 | { 147 | "include": "#keywords" 148 | }, 149 | { 150 | "include": "#cexprs" 151 | }, 152 | { 153 | "include": "#text" 154 | } 155 | ] 156 | }, 157 | "strp_inlined": { 158 | "patterns": [ 159 | { 160 | "begin": "(\\()", 161 | "beginCaptures": { 162 | "1": { 163 | "name": "keyword.symbol.fsharp" 164 | } 165 | }, 166 | "end": "(\\))", 167 | "endCaptures": { 168 | "1": { 169 | "name": "keyword.symbol.fsharp" 170 | } 171 | }, 172 | "patterns": [ 173 | { 174 | "include": "#strp_inlined_body" 175 | } 176 | ] 177 | } 178 | ] 179 | }, 180 | "generic_declaration": { 181 | "patterns": [ 182 | { 183 | "comments": "SRTP syntax support", 184 | "begin": "(:)\\s*(\\()\\s*(static member|member)", 185 | "beginCaptures": { 186 | "1": { 187 | "name": "keyword.symbol.fsharp" 188 | }, 189 | "2": { 190 | "name": "keyword.symbol.fsharp" 191 | }, 192 | "3": { 193 | "name": "keyword.fsharp" 194 | } 195 | }, 196 | "end": "(\\))", 197 | "endCaptures": { 198 | "1": { 199 | "name": "keyword.symbol.fsharp" 200 | } 201 | }, 202 | "patterns": [ 203 | { 204 | "begin": "(\\()", 205 | "beginCaptures": { 206 | "1": { 207 | "name": "keyword.symbol.fsharp" 208 | } 209 | }, 210 | "end": "(\\))", 211 | "endCaptures": { 212 | "1": { 213 | "name": "keyword.symbol.fsharp" 214 | } 215 | }, 216 | "patterns": [ 217 | { 218 | "include": "#member_declaration" 219 | } 220 | ] 221 | }, 222 | { 223 | "match": "(('|\\^)[[:alpha:]0-9'._]+)", 224 | "captures": { 225 | "1": { 226 | "name": "entity.name.type.fsharp" 227 | } 228 | } 229 | }, 230 | { 231 | "include": "#variables" 232 | }, 233 | { 234 | "include": "#keywords" 235 | } 236 | ] 237 | }, 238 | { 239 | "name": "keyword.fsharp", 240 | "match": "\\b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\\!|return\\!|return|interface|with|abstract|property|union|enum|member|try|finally|and|when|use|use\\!|struct|while|mutable)(?!')\\b" 241 | }, 242 | { 243 | "name": "keyword.fsharp", 244 | "match": ":" 245 | }, 246 | { 247 | "include": "#constants" 248 | }, 249 | { 250 | "match": "(('|\\^)[[:alpha:]0-9'._]+)", 251 | "captures": { 252 | "1": { 253 | "name": "entity.name.type.fsharp" 254 | } 255 | } 256 | }, 257 | { 258 | "begin": "(<)", 259 | "end": "(>)", 260 | "beginCaptures": { 261 | "1": { 262 | "name": "keyword.symbol.fsharp" 263 | } 264 | }, 265 | "endCaptures": { 266 | "1": { 267 | "name": "keyword.symbol.fsharp" 268 | } 269 | }, 270 | "patterns": [ 271 | { 272 | "match": "(('|\\^)[[:alpha:]0-9'._]+)", 273 | "captures": { 274 | "1": { 275 | "name": "entity.name.type.fsharp" 276 | } 277 | } 278 | }, 279 | { 280 | "include": "#tuple_signature" 281 | }, 282 | { 283 | "include": "#generic_declaration" 284 | } 285 | ] 286 | }, 287 | { 288 | "begin": "(\\()", 289 | "end": "(\\))", 290 | "beginCaptures": { 291 | "1": { 292 | "name": "keyword.symbol.fsharp" 293 | } 294 | }, 295 | "endCaptures": { 296 | "1": { 297 | "name": "keyword.symbol.fsharp" 298 | } 299 | }, 300 | "patterns": [ 301 | { 302 | "match": "(([?[:alpha:]0-9'`^._ ]+))+", 303 | "captures": { 304 | "1": { 305 | "name": "entity.name.type.fsharp" 306 | } 307 | } 308 | }, 309 | { 310 | "include": "#tuple_signature" 311 | } 312 | ] 313 | }, 314 | { 315 | "match": "(?!when|and|or\\b)\\b([\\w0-9'`^._]+)", 316 | "comments": "Here we need the \\w modifier in order to check that the words isn't blacklisted", 317 | "captures": { 318 | "1": { 319 | "name": "entity.name.type.fsharp" 320 | } 321 | } 322 | }, 323 | { 324 | "match": "(\\|)", 325 | "comments": "Prevent captures of `|>` as a keyword when defining custom operator like `<|>`", 326 | "captures": { 327 | "1": { 328 | "name": "keyword.symbol.fsharp" 329 | } 330 | } 331 | }, 332 | { 333 | "include": "#keywords" 334 | } 335 | ] 336 | }, 337 | "anonymous_record_declaration": { 338 | "begin": "(\\{\\|)", 339 | "end": "(\\|\\})", 340 | "beginCaptures": { 341 | "1": { 342 | "name": "keyword.symbol.fsharp" 343 | } 344 | }, 345 | "endCaptures": { 346 | "1": { 347 | "name": "keyword.symbol.fsharp" 348 | } 349 | }, 350 | "patterns": [ 351 | { 352 | "match": "[[:alpha:]0-9'`^_ ]+(:)", 353 | "captures": { 354 | "1": { 355 | "name": "keyword.symbol.fsharp" 356 | } 357 | } 358 | }, 359 | { 360 | "match": "([[:alpha:]0-9'`^_ ]+)", 361 | "captures": { 362 | "1": { 363 | "name": "entity.name.type.fsharp" 364 | } 365 | } 366 | }, 367 | { 368 | "include": "#anonymous_record_declaration" 369 | }, 370 | { 371 | "include": "#keywords" 372 | } 373 | ] 374 | }, 375 | "record_signature": { 376 | "patterns": [ 377 | { 378 | "match": "[[:alpha:]0-9'`^_ ]+(=)([[:alpha:]0-9'`^_ ]+)", 379 | "captures": { 380 | "1": { 381 | "name": "keyword.symbol.fsharp" 382 | }, 383 | "2": { 384 | "name": "variable.parameter.fsharp" 385 | } 386 | } 387 | }, 388 | { 389 | "begin": "({)", 390 | "end": "(})", 391 | "beginCaptures": { 392 | "1": { 393 | "name": "keyword.symbol.fsharp" 394 | } 395 | }, 396 | "endCaptures": { 397 | "1": { 398 | "name": "keyword.symbol.fsharp" 399 | } 400 | }, 401 | "patterns": [ 402 | { 403 | "match": "[[:alpha:]0-9'`^_ ]+(=)([[:alpha:]0-9'`^_ ]+)", 404 | "captures": { 405 | "1": { 406 | "name": "keyword.symbol.fsharp" 407 | }, 408 | "2": { 409 | "name": "variable.parameter.fsharp" 410 | } 411 | } 412 | }, 413 | { 414 | "include": "#record_signature" 415 | } 416 | ] 417 | }, 418 | { 419 | "include": "#keywords" 420 | } 421 | ] 422 | }, 423 | "tuple_signature": { 424 | "patterns": [ 425 | { 426 | "match": "(([?[:alpha:]0-9'`^._ ]+))+", 427 | "captures": { 428 | "1": { 429 | "name": "entity.name.type.fsharp" 430 | } 431 | } 432 | }, 433 | { 434 | "begin": "(\\()", 435 | "end": "(\\))", 436 | "beginCaptures": { 437 | "1": { 438 | "name": "keyword.symbol.fsharp" 439 | } 440 | }, 441 | "endCaptures": { 442 | "1": { 443 | "name": "keyword.symbol.fsharp" 444 | } 445 | }, 446 | "patterns": [ 447 | { 448 | "match": "(([?[:alpha:]0-9'`^._ ]+))+", 449 | "captures": { 450 | "1": { 451 | "name": "entity.name.type.fsharp" 452 | } 453 | } 454 | }, 455 | { 456 | "include": "#tuple_signature" 457 | } 458 | ] 459 | }, 460 | { 461 | "include": "#keywords" 462 | } 463 | ] 464 | }, 465 | "anonymous_functions": { 466 | "patterns": [ 467 | { 468 | "name": "function.anonymous", 469 | "begin": "\\b(fun)\\b", 470 | "end": "(->)", 471 | "beginCaptures": { 472 | "1": { 473 | "name": "keyword.fsharp" 474 | } 475 | }, 476 | "endCaptures": { 477 | "1": { 478 | "name": "keyword.fsharp" 479 | } 480 | }, 481 | "patterns": [ 482 | { 483 | "include": "#comments" 484 | }, 485 | { 486 | "begin": "(\\()", 487 | "end": "\\s*(?=(->))", 488 | "beginCaptures": { 489 | "1": { 490 | "name": "keyword.symbol.fsharp" 491 | } 492 | }, 493 | "endCaptures": { 494 | "1": { 495 | "name": "keyword.symbol.fsharp" 496 | } 497 | }, 498 | "patterns": [ 499 | { 500 | "include": "#member_declaration" 501 | } 502 | ] 503 | }, 504 | { 505 | "include": "#variables" 506 | } 507 | ] 508 | } 509 | ] 510 | }, 511 | "attributes": { 512 | "patterns": [ 513 | { 514 | "name": "support.function.attribute.fsharp", 515 | "begin": "\\[\\<", 516 | "end": "\\>\\]|\\]", 517 | "patterns": [ 518 | { 519 | "include": "$self" 520 | } 521 | ] 522 | } 523 | ] 524 | }, 525 | "comments": { 526 | "patterns": [ 527 | { 528 | "name": "comment.block.markdown.fsharp", 529 | "begin": "^\\s*(\\(\\*\\*(?!\\)))(?!\\*\\))$", 530 | "while": "^(?!\\s*\\*\\)$)", 531 | "beginCaptures": { 532 | "1": { 533 | "name": "comment.block.fsharp" 534 | } 535 | }, 536 | "endCaptures": { 537 | "1": { 538 | "name": "comment.block.fsharp" 539 | } 540 | }, 541 | "patterns": [ 542 | { 543 | "include": "text.html.markdown" 544 | } 545 | ] 546 | }, 547 | { 548 | "name": "comment.block.markdown.fsharp.end", 549 | "match": "^(\\s*\\*\\)$)", 550 | "captures": { 551 | "1": { 552 | "name": "comment.block.fsharp" 553 | } 554 | } 555 | }, 556 | { 557 | "name": "comment.block.fsharp", 558 | "begin": "(\\(\\*(?!\\)))", 559 | "end": "(\\*\\))", 560 | "beginCaptures": { 561 | "1": { 562 | "name": "comment.block.fsharp" 563 | } 564 | }, 565 | "endCaptures": { 566 | "1": { 567 | "name": "comment.block.fsharp" 568 | } 569 | } 570 | }, 571 | { 572 | "name": "comment.line.markdown.fsharp", 573 | "begin": "///", 574 | "while": "///", 575 | "patterns": [ 576 | { 577 | "include": "text.html.markdown" 578 | } 579 | ] 580 | }, 581 | { 582 | "name": "comment.line.double-slash.fsharp", 583 | "match": "//.*$" 584 | } 585 | ] 586 | }, 587 | "constants": { 588 | "patterns": [ 589 | { 590 | "name": "constant.language.unit.fsharp", 591 | "match": "\\(\\)" 592 | }, 593 | { 594 | "name": "constant.numeric.floating-point.fsharp", 595 | "match": "\\b-?[0-9][0-9_]*((\\.([0-9][0-9_]*([eE][+-]??[0-9][0-9_]*)?)?)|([eE][+-]??[0-9][0-9_]*))" 596 | }, 597 | { 598 | "name": "constant.numeric.integer.nativeint.fsharp", 599 | "match": "\\b(-?((0(x|X)[0-9a-fA-F][0-9a-fA-F_]*)|(0(o|O)[0-7][0-7_]*)|(0(b|B)[01][01_]*)|([0-9][0-9_]*)))" 600 | }, 601 | { 602 | "name": "constant.others.fsharp", 603 | "match": "\\b(true|false|null|unit)\\b" 604 | } 605 | ] 606 | }, 607 | "abstract_definition": { 608 | "name": "abstract.definition.fsharp", 609 | "begin": "\\b(abstract)\\s+(member)?(\\s+\\[\\<.*\\>\\])?\\s*([_[:alpha:]0-9,\\._`\\s]+)(:)", 610 | "end": "\\s*(with)\\b|=|$", 611 | "beginCaptures": { 612 | "1": { 613 | "name": "keyword.fsharp" 614 | }, 615 | "2": { 616 | "name": "keyword.fsharp" 617 | }, 618 | "3": { 619 | "name": "support.function.attribute.fsharp" 620 | }, 621 | "5": { 622 | "name": "keyword.fsharp" 623 | } 624 | }, 625 | "endCaptures": { 626 | "1": { 627 | "name": "keyword.fsharp" 628 | } 629 | }, 630 | "patterns": [ 631 | { 632 | "include": "#comments" 633 | }, 634 | { 635 | "include": "#common_declaration" 636 | }, 637 | { 638 | "match": "(\\?{0,1})([[:alpha:]0-9'`^._ ]+)\\s*(:)((?!with\\b)\\b([\\w0-9'`^._ ]+)){0,1}", 639 | "captures": { 640 | "1": { 641 | "name": "keyword.symbol.fsharp" 642 | }, 643 | "2": { 644 | "name": "variable.parameter.fsharp" 645 | }, 646 | "3": { 647 | "name": "keyword.symbol.fsharp" 648 | }, 649 | "4": { 650 | "name": "entity.name.type.fsharp" 651 | } 652 | } 653 | }, 654 | { 655 | "match": "(?!with|get|set\\b)\\b([\\w0-9'`^._]+)", 656 | "comments": "Here we need the \\w modifier in order to check that the words isn't blacklisted", 657 | "captures": { 658 | "1": { 659 | "name": "entity.name.type.fsharp" 660 | } 661 | } 662 | }, 663 | { 664 | "include": "#keywords" 665 | } 666 | ] 667 | }, 668 | "common_binding_definition": { 669 | "patterns": [ 670 | { 671 | "include": "#comments" 672 | }, 673 | { 674 | "include": "#attributes" 675 | }, 676 | { 677 | "comments": "SRTP syntax support", 678 | "begin": "(:)\\s*(\\()\\s*(static member|member)", 679 | "beginCaptures": { 680 | "1": { 681 | "name": "keyword.symbol.fsharp" 682 | }, 683 | "2": { 684 | "name": "keyword.symbol.fsharp" 685 | }, 686 | "3": { 687 | "name": "keyword.fsharp" 688 | } 689 | }, 690 | "end": "(\\))\\s*((?=,)|(?=\\=))", 691 | "endCaptures": { 692 | "1": { 693 | "name": "keyword.symbol.fsharp" 694 | } 695 | }, 696 | "patterns": [ 697 | { 698 | "match": "(\\^[[:alpha:]0-9'._]+)", 699 | "captures": { 700 | "1": { 701 | "name": "entity.name.type.fsharp" 702 | } 703 | } 704 | }, 705 | { 706 | "include": "#variables" 707 | }, 708 | { 709 | "include": "#keywords" 710 | } 711 | ] 712 | }, 713 | { 714 | "begin": "(:)\\s*(\\()", 715 | "beginCaptures": { 716 | "1": { 717 | "name": "keyword.symbol.fsharp" 718 | }, 719 | "2": { 720 | "name": "keyword.symbol.fsharp" 721 | } 722 | }, 723 | "end": "(\\)\\s*(([?[:alpha:]0-9'`^._ ]*)))", 724 | "endCaptures": { 725 | "1": { 726 | "name": "keyword.symbol.fsharp" 727 | }, 728 | "2": { 729 | "name": "entity.name.type.fsharp" 730 | } 731 | }, 732 | "patterns": [ 733 | { 734 | "include": "#tuple_signature" 735 | } 736 | ] 737 | }, 738 | { 739 | "begin": "(:)\\s*(\\^[[:alpha:]0-9'._]+)\\s*(when)", 740 | "beginCaptures": { 741 | "1": { 742 | "name": "keyword.symbol.fsharp" 743 | }, 744 | "2": { 745 | "name": "entity.name.type.fsharp" 746 | }, 747 | "3": { 748 | "name": "keyword.fsharp" 749 | } 750 | }, 751 | "end": "(?=:)", 752 | "endCaptures": { 753 | "1": { 754 | "name": "keyword.symbol.fsharp" 755 | } 756 | }, 757 | "patterns": [ 758 | { 759 | "name": "keyword.fsharp", 760 | "match": "\\b(and|when|or)\\b" 761 | }, 762 | { 763 | "comment": "Because we first capture the keywords, we can capture what looks like a word and assume it's an entity definition", 764 | "match": "([[:alpha:]0-9'^._]+)", 765 | "captures": { 766 | "1": { 767 | "name": "entity.name.type.fsharp" 768 | } 769 | } 770 | }, 771 | { 772 | "name": "keyword.symbol.fsharp", 773 | "match": "(\\(|\\))" 774 | } 775 | ] 776 | }, 777 | { 778 | "match": "(:)\\s*([?[:alpha:]0-9'`^._ ]+)", 779 | "captures": { 780 | "1": { 781 | "name": "keyword.symbol.fsharp" 782 | }, 783 | "2": { 784 | "name": "entity.name.type.fsharp" 785 | } 786 | } 787 | }, 788 | { 789 | "match": "(->)\\s*(\\()?\\s*([?[:alpha:]0-9'`^._ ]+)*", 790 | "captures": { 791 | "1": { 792 | "name": "keyword.symbol.fsharp" 793 | }, 794 | "2": { 795 | "name": "keyword.symbol.fsharp" 796 | }, 797 | "3": { 798 | "name": "entity.name.type.fsharp" 799 | } 800 | } 801 | }, 802 | { 803 | "begin": "(\\*)\\s*(\\()", 804 | "beginCaptures": { 805 | "1": { 806 | "name": "keyword.symbol.fsharp" 807 | }, 808 | "2": { 809 | "name": "keyword.symbol.fsharp" 810 | } 811 | }, 812 | "end": "(\\)\\s*(([?[:alpha:]0-9'`^._ ]+))+)", 813 | "endCaptures": { 814 | "1": { 815 | "name": "keyword.symbol.fsharp" 816 | }, 817 | "2": { 818 | "name": "entity.name.type.fsharp" 819 | } 820 | }, 821 | "patterns": [ 822 | { 823 | "include": "#tuple_signature" 824 | } 825 | ] 826 | }, 827 | { 828 | "match": "(\\*)(\\s*([?[:alpha:]0-9'`^._ ]+))*", 829 | "captures": { 830 | "1": { 831 | "name": "keyword.symbol.fsharp" 832 | }, 833 | "2": { 834 | "name": "entity.name.type.fsharp" 835 | } 836 | } 837 | }, 838 | { 839 | "begin": "(<+(?![[:space:]]*\\)))", 840 | "beginComment": "The group (?![[:space:]]*\\) is for protection against overload operator. static member (<)", 841 | "end": "((?|\\))", 842 | "endComment": "The group (? when using SRTP synthax", 843 | "beginCaptures": { 844 | "1": { 845 | "name": "keyword.symbol.fsharp" 846 | } 847 | }, 848 | "endCaptures": { 849 | "1": { 850 | "name": "keyword.symbol.fsharp" 851 | } 852 | }, 853 | "patterns": [ 854 | { 855 | "include": "#generic_declaration" 856 | } 857 | ] 858 | }, 859 | { 860 | "include": "#anonymous_record_declaration" 861 | }, 862 | { 863 | "begin": "({)", 864 | "end": "(})", 865 | "beginCaptures": { 866 | "1": { 867 | "name": "keyword.symbol.fsharp" 868 | } 869 | }, 870 | "endCaptures": { 871 | "1": { 872 | "name": "keyword.symbol.fsharp" 873 | } 874 | }, 875 | "patterns": [ 876 | { 877 | "include": "#record_signature" 878 | } 879 | ] 880 | }, 881 | { 882 | "include": "#definition" 883 | }, 884 | { 885 | "match": "(?<=>)\\s*(``([[:alpha:]0-9'^._ ]+)``|[[:alpha:]0-9'`^._]+)", 886 | "captures": { 887 | "1": { 888 | "name": "entity.name.type.fsharp" 889 | } 890 | } 891 | }, 892 | { 893 | "include": "#variables" 894 | }, 895 | { 896 | "include": "#keywords" 897 | } 898 | ] 899 | }, 900 | "definition": { 901 | "patterns": [ 902 | { 903 | "name": "binding.fsharp", 904 | "begin": "\\b(let mutable|static let mutable|let inline|let|member val|static member inline|static member|default|member|override|let!)(\\s+rec|mutable)?(\\s+\\[\\<.*\\>\\])?\\s*(private|internal|public)?\\s+(\\[[^-=]*\\]|[_[:alpha:]]([_[:alpha:]0-9\\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9\\._`\\s]+|(?<=,)\\s)*)?", 905 | "end": "\\s*(with\\b|=|\\n+=|(?<=\\=))", 906 | "beginCaptures": { 907 | "1": { 908 | "name": "keyword.fsharp" 909 | }, 910 | "2": { 911 | "name": "keyword.fsharp" 912 | }, 913 | "3": { 914 | "name": "support.function.attribute.fsharp" 915 | }, 916 | "4": { 917 | "name": "keyword.fsharp" 918 | }, 919 | "5": { 920 | "name": "variable.fsharp" 921 | } 922 | }, 923 | "endCaptures": { 924 | "1": { 925 | "name": "keyword.fsharp" 926 | } 927 | }, 928 | "patterns": [ 929 | { 930 | "include": "#common_binding_definition" 931 | } 932 | ] 933 | }, 934 | { 935 | "name": "binding.fsharp", 936 | "begin": "\\b((get|set)\\s*(?=\\())(\\[[^-=]*\\]|[_[:alpha:]]([_[:alpha:]0-9\\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9\\._`\\s]+|(?<=,)\\s)*)?", 937 | "end": "\\s*(=|\\n+=|(?<=\\=))", 938 | "beginCaptures": { 939 | "3": { 940 | "name": "variable.fsharp" 941 | } 942 | }, 943 | "endCaptures": { 944 | "1": { 945 | "name": "keyword.fsharp" 946 | } 947 | }, 948 | "patterns": [ 949 | { 950 | "include": "#common_binding_definition" 951 | } 952 | ] 953 | }, 954 | { 955 | "name": "binding.fsharp", 956 | "begin": "\\b(static val mutable|val mutable|val)(\\s+rec|mutable)?(\\s+\\[\\<.*\\>\\])?\\s*(private|internal|public)?\\s+(\\[[^-=]*\\]|[_[:alpha:]]([_[:alpha:]0-9,\\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9,\\._`\\s]+|(?<=,)\\s)*)?", 957 | "end": "\\n$", 958 | "beginCaptures": { 959 | "1": { 960 | "name": "keyword.fsharp" 961 | }, 962 | "2": { 963 | "name": "keyword.fsharp" 964 | }, 965 | "3": { 966 | "name": "support.function.attribute.fsharp" 967 | }, 968 | "4": { 969 | "name": "keyword.fsharp" 970 | }, 971 | "5": { 972 | "name": "variable.fsharp" 973 | } 974 | }, 975 | "patterns": [ 976 | { 977 | "include": "#common_binding_definition" 978 | } 979 | ] 980 | } 981 | ] 982 | }, 983 | "du_declaration": { 984 | "patterns": [ 985 | { 986 | "name": "du_declaration.fsharp", 987 | "begin": "\\b(of)\\b", 988 | "end": "$|(\\|)", 989 | "beginCaptures": { 990 | "1": { 991 | "name": "keyword.fsharp" 992 | } 993 | }, 994 | "endCaptures": { 995 | "1": { 996 | "name": "keyword.symbol.fsharp" 997 | } 998 | }, 999 | "patterns": [ 1000 | { 1001 | "include": "#comments" 1002 | }, 1003 | { 1004 | "match": "([[:alpha:]0-9'`<>^._]+|``[[:alpha:]0-9' <>^._]+``)\\s*(:)\\s*([[:alpha:]0-9'`<>^._]+|``[[:alpha:]0-9' <>^._]+``)", 1005 | "captures": { 1006 | "1": { 1007 | "name": "variable.parameter.fsharp" 1008 | }, 1009 | "2": { 1010 | "name": "keyword.symbol.fsharp" 1011 | }, 1012 | "3": { 1013 | "name": "entity.name.type.fsharp" 1014 | } 1015 | } 1016 | }, 1017 | { 1018 | "match": "(``([[:alpha:]0-9'^._ ]+)``|[[:alpha:]0-9'`^._]+)", 1019 | "captures": { 1020 | "1": { 1021 | "name": "entity.name.type.fsharp" 1022 | } 1023 | } 1024 | }, 1025 | { 1026 | "include": "#anonymous_record_declaration" 1027 | }, 1028 | { 1029 | "include": "#keywords" 1030 | } 1031 | ] 1032 | } 1033 | ] 1034 | }, 1035 | "keywords": { 1036 | "patterns": [ 1037 | { 1038 | "name": "keyword.fsharp", 1039 | "match": "\\b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\\!|return\\!|return|interface|with|abstract|property|union|enum|member|try|finally|and|when|or|use|use\\!|struct|while|mutable)(?!')\\b" 1040 | }, 1041 | { 1042 | "name": "keyword.symbol.fsharp", 1043 | "match": "(&&&|\\|\\|\\||\\^\\^\\^|~~~|<<<|>>>|\\|>|\\->|\\<\\-|:>|:\\?>|:|\\[|\\]|\\;|<>|=|@|\\|\\||&&|{|}|\\||_|\\.\\.|\\,|\\+|\\-|\\*|\\/|\\^|\\!|\\>|\\>\\=|\\>\\>|\\<|\\<\\=|\\(|\\)|\\<\\<)" 1044 | } 1045 | ] 1046 | }, 1047 | "modules": { 1048 | "patterns": [ 1049 | { 1050 | "name": "entity.name.section.fsharp", 1051 | "begin": "\\b(namespace|module)\\s*(public|internal|private)?\\s+([[:alpha:]][[:alpha:]0-9'_. ]*)", 1052 | "end": "(\\s?=|\\s|$)", 1053 | "beginCaptures": { 1054 | "1": { 1055 | "name": "keyword.fsharp" 1056 | }, 1057 | "2": { 1058 | "name": "keyword.fsharp" 1059 | }, 1060 | "3": { 1061 | "name": "entity.name.section.fsharp" 1062 | } 1063 | }, 1064 | "endCaptures": { 1065 | "1": { 1066 | "name": "keyword.symbol.fsharp" 1067 | } 1068 | }, 1069 | "patterns": [ 1070 | { 1071 | "name": "entity.name.section.fsharp", 1072 | "match": "(\\.)([A-Z][[:alpha:]0-9'_]*)", 1073 | "captures": { 1074 | "1": { 1075 | "name": "punctuation.separator.namespace-reference.fsharp" 1076 | }, 1077 | "2": { 1078 | "name": "entity.name.section.fsharp" 1079 | } 1080 | } 1081 | } 1082 | ] 1083 | }, 1084 | { 1085 | "name": "namespace.open.fsharp", 1086 | "begin": "\\b(open)\\s+([[:alpha:]][[:alpha:]0-9'_]*)(?=(\\.[A-Z][[:alpha:]0-9_]*)*)", 1087 | "end": "(\\s|$)", 1088 | "beginCaptures": { 1089 | "1": { 1090 | "name": "keyword.fsharp" 1091 | }, 1092 | "2": { 1093 | "name": "entity.name.section.fsharp" 1094 | } 1095 | }, 1096 | "patterns": [ 1097 | { 1098 | "name": "entity.name.section.fsharp", 1099 | "match": "(\\.)([[:alpha:]][[:alpha:]0-9'_]*)", 1100 | "captures": { 1101 | "1": { 1102 | "name": "punctuation.separator.namespace-reference.fsharp" 1103 | }, 1104 | "2": { 1105 | "name": "entity.name.section.fsharp" 1106 | } 1107 | } 1108 | }, 1109 | { 1110 | "include": "#comments" 1111 | } 1112 | ] 1113 | }, 1114 | { 1115 | "name": "namespace.alias.fsharp", 1116 | "begin": "^\\s*(module)\\s+([A-Z][[:alpha:]0-9'_]*)\\s*(=)\\s*([A-Z][[:alpha:]0-9'_]*)", 1117 | "end": "(\\s|$)", 1118 | "beginCaptures": { 1119 | "1": { 1120 | "name": "keyword.fsharp" 1121 | }, 1122 | "2": { 1123 | "name": "entity.name.type.namespace.fsharp" 1124 | }, 1125 | "3": { 1126 | "name": "punctuation.separator.namespace-definition.fsharp" 1127 | }, 1128 | "4": { 1129 | "name": "entity.name.section.fsharp" 1130 | } 1131 | }, 1132 | "patterns": [ 1133 | { 1134 | "name": "entity.name.section.fsharp", 1135 | "match": "(\\.)([A-Z][[:alpha:]0-9'_]*)", 1136 | "captures": { 1137 | "1": { 1138 | "name": "punctuation.separator.namespace-reference.fsharp" 1139 | }, 1140 | "2": { 1141 | "name": "entity.name.section.fsharp" 1142 | } 1143 | } 1144 | } 1145 | ] 1146 | } 1147 | ] 1148 | }, 1149 | "strings": { 1150 | "patterns": [ 1151 | { 1152 | "name": "string.quoted.literal.fsharp", 1153 | "begin": "(?=[^\\\\])(@\")", 1154 | "end": "(\")(?!\")", 1155 | "beginCaptures": { 1156 | "1": { 1157 | "name": "punctuation.definition.string.begin.fsharp" 1158 | } 1159 | }, 1160 | "endCaptures": { 1161 | "1": { 1162 | "name": "punctuation.definition.string.end.fsharp" 1163 | } 1164 | }, 1165 | "patterns": [ 1166 | { 1167 | "name": "constant.character.string.escape.fsharp", 1168 | "match": "\"(\")" 1169 | } 1170 | ] 1171 | }, 1172 | { 1173 | "name": "string.quoted.triple.fsharp", 1174 | "begin": "(?=[^\\\\])(\"\"\")", 1175 | "end": "(\"\"\")", 1176 | "beginCaptures": { 1177 | "1": { 1178 | "name": "punctuation.definition.string.begin.fsharp" 1179 | } 1180 | }, 1181 | "endCaptures": { 1182 | "1": { 1183 | "name": "punctuation.definition.string.end.fsharp" 1184 | } 1185 | }, 1186 | "patterns": [ 1187 | { 1188 | "include": "#string_formatter" 1189 | } 1190 | ] 1191 | }, 1192 | { 1193 | "name": "string.quoted.double.fsharp", 1194 | "begin": "(?=[^\\\\])(\")", 1195 | "end": "(\")", 1196 | "beginCaptures": { 1197 | "1": { 1198 | "name": "punctuation.definition.string.begin.fsharp" 1199 | } 1200 | }, 1201 | "endCaptures": { 1202 | "1": { 1203 | "name": "punctuation.definition.string.end.fsharp" 1204 | } 1205 | }, 1206 | "patterns": [ 1207 | { 1208 | "name": "punctuation.separator.string.ignore-eol.fsharp", 1209 | "match": "\\\\$[ \\t]*" 1210 | }, 1211 | { 1212 | "name": "constant.character.string.escape.fsharp", 1213 | "match": "\\\\([\\\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})" 1214 | }, 1215 | { 1216 | "name": "invalid.illeagal.character.string.fsharp", 1217 | "match": "\\\\(?![\\\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})." 1218 | }, 1219 | { 1220 | "include": "#string_formatter" 1221 | } 1222 | ] 1223 | } 1224 | ] 1225 | }, 1226 | "string_formatter": { 1227 | "patterns": [ 1228 | { 1229 | "name": "entity.name.type.format.specifier.fsharp", 1230 | "match": "(%0?-?(\\d+)?((a|t)|(\\.\\d+)?(f|F|e|E|g|G|M)|(b|c|s|d|i|x|X|o|u)|(s|b|O)|(\\+?A)))", 1231 | "captures": { 1232 | "1": { 1233 | "name": "keyword.format.specifier.fsharp" 1234 | } 1235 | } 1236 | } 1237 | ] 1238 | }, 1239 | "variables": { 1240 | "patterns": [ 1241 | { 1242 | "name": "constant.language.unit.fsharp", 1243 | "match": "\\(\\)" 1244 | }, 1245 | { 1246 | "match": "(\\?{0,1})(``[[:alpha:]0-9'`^:,._ ]+``|(?!private\\b)\\b[\\w[:alpha:]0-9'`<>^._ ]+)", 1247 | "captures": { 1248 | "1": { 1249 | "name": "keyword.symbol.fsharp" 1250 | }, 1251 | "2": { 1252 | "name": "variable.parameter.fsharp" 1253 | } 1254 | } 1255 | } 1256 | ] 1257 | }, 1258 | "common_declaration": { 1259 | "patterns": [ 1260 | { 1261 | "begin": "\\s*(->)\\s*([[:alpha:]0-9'`^._ ]+)(<)", 1262 | "end": "(>)", 1263 | "beginCaptures": { 1264 | "1": { 1265 | "name": "keyword.symbol.fsharp" 1266 | }, 1267 | "2": { 1268 | "name": "entity.name.type.fsharp" 1269 | }, 1270 | "3": { 1271 | "name": "keyword.symbol.fsharp" 1272 | } 1273 | }, 1274 | "endCaptures": { 1275 | "1": { 1276 | "name": "keyword.symbol.fsharp" 1277 | } 1278 | }, 1279 | "patterns": [ 1280 | { 1281 | "match": "([[:alpha:]0-9'`^._ ]+)", 1282 | "captures": { 1283 | "1": { 1284 | "name": "entity.name.type.fsharp" 1285 | } 1286 | } 1287 | }, 1288 | { 1289 | "include": "#keywords" 1290 | } 1291 | ] 1292 | }, 1293 | { 1294 | "match": "\\s*(->)\\s*(?!with|get|set\\b)\\b([\\w0-9'`^._]+)", 1295 | "captures": { 1296 | "1": { 1297 | "name": "keyword.symbol.fsharp" 1298 | }, 1299 | "2": { 1300 | "name": "entity.name.type.fsharp" 1301 | } 1302 | } 1303 | }, 1304 | { 1305 | "include": "#anonymous_record_declaration" 1306 | }, 1307 | { 1308 | "begin": "(\\?{0,1})([[:alpha:]0-9'`^._ ]+)\\s*(:)(\\s*([?[:alpha:]0-9'`^._ ]+)(<))", 1309 | "end": "(>)", 1310 | "beginCaptures": { 1311 | "1": { 1312 | "name": "keyword.symbol.fsharp" 1313 | }, 1314 | "2": { 1315 | "name": "variable.parameter.fsharp" 1316 | }, 1317 | "3": { 1318 | "name": "keyword.symbol.fsharp" 1319 | }, 1320 | "4": { 1321 | "name": "keyword.symbol.fsharp" 1322 | }, 1323 | "5": { 1324 | "name": "entity.name.type.fsharp" 1325 | } 1326 | }, 1327 | "endCaptures": { 1328 | "1": { 1329 | "name": "keyword.symbol.fsharp" 1330 | } 1331 | }, 1332 | "patterns": [ 1333 | { 1334 | "match": "([[:alpha:]0-9'`^._ ]+)", 1335 | "captures": { 1336 | "1": { 1337 | "name": "entity.name.type.fsharp" 1338 | } 1339 | } 1340 | }, 1341 | { 1342 | "include": "#keywords" 1343 | } 1344 | ] 1345 | } 1346 | ] 1347 | }, 1348 | "member_declaration": { 1349 | "patterns": [ 1350 | { 1351 | "include": "#comments" 1352 | }, 1353 | { 1354 | "include": "#common_declaration" 1355 | }, 1356 | { 1357 | "comments": "SRTP syntax support", 1358 | "begin": "(:)\\s*(\\()\\s*(static member|member)", 1359 | "beginCaptures": { 1360 | "1": { 1361 | "name": "keyword.symbol.fsharp" 1362 | }, 1363 | "2": { 1364 | "name": "keyword.symbol.fsharp" 1365 | }, 1366 | "3": { 1367 | "name": "keyword.fsharp" 1368 | } 1369 | }, 1370 | "end": "(\\))\\s*((?=,)|(?=\\=))", 1371 | "endCaptures": { 1372 | "1": { 1373 | "name": "keyword.symbol.fsharp" 1374 | } 1375 | }, 1376 | "patterns": [ 1377 | { 1378 | "begin": "(\\()", 1379 | "beginCaptures": { 1380 | "1": { 1381 | "name": "keyword.symbol.fsharp" 1382 | } 1383 | }, 1384 | "end": "(\\))", 1385 | "endCaptures": { 1386 | "1": { 1387 | "name": "keyword.symbol.fsharp" 1388 | } 1389 | }, 1390 | "patterns": [ 1391 | { 1392 | "include": "#member_declaration" 1393 | } 1394 | ] 1395 | }, 1396 | { 1397 | "match": "(\\^[[:alpha:]0-9'._]+)", 1398 | "captures": { 1399 | "1": { 1400 | "name": "entity.name.type.fsharp" 1401 | } 1402 | } 1403 | }, 1404 | { 1405 | "include": "#variables" 1406 | }, 1407 | { 1408 | "include": "#keywords" 1409 | } 1410 | ] 1411 | }, 1412 | { 1413 | "match": "(\\^[[:alpha:]0-9'._]+)", 1414 | "captures": { 1415 | "1": { 1416 | "name": "entity.name.type.fsharp" 1417 | } 1418 | } 1419 | }, 1420 | { 1421 | "name": "keyword.fsharp", 1422 | "match": "\\b(and|when|or)\\b" 1423 | }, 1424 | { 1425 | "name": "keyword.symbol.fsharp", 1426 | "match": "(\\(|\\))" 1427 | }, 1428 | { 1429 | "match": "(\\?{0,1})([[:alpha:]0-9'`^._]+|``[[:alpha:]0-9'`^:,._ ]+``)\\s*(:{0,1})(\\s*([?[:alpha:]0-9'`<>._ ]+)){0,1}", 1430 | "captures": { 1431 | "1": { 1432 | "name": "keyword.symbol.fsharp" 1433 | }, 1434 | "2": { 1435 | "name": "variable.parameter.fsharp" 1436 | }, 1437 | "3": { 1438 | "name": "keyword.symbol.fsharp" 1439 | }, 1440 | "4": { 1441 | "name": "entity.name.type.fsharp" 1442 | } 1443 | } 1444 | }, 1445 | { 1446 | "include": "#keywords" 1447 | } 1448 | ] 1449 | }, 1450 | "double_tick": { 1451 | "patterns": [ 1452 | { 1453 | "name": "variable.other.binding.fsharp", 1454 | "match": "(``)(.*)(``)", 1455 | "captures": { 1456 | "1": { 1457 | "name": "string.quoted.single.fsharp" 1458 | }, 1459 | "2": { 1460 | "name": "variable.other.binding.fsharp" 1461 | }, 1462 | "3": { 1463 | "name": "string.quoted.single.fsharp" 1464 | } 1465 | } 1466 | } 1467 | ] 1468 | }, 1469 | "records": { 1470 | "patterns": [ 1471 | { 1472 | "name": "record.fsharp", 1473 | "begin": "\\b(type)[\\s]+(private|internal|public)?\\s*", 1474 | "end": "\\s*((with)|((as)\\s+([[:alpha:]0-9']+))|(=)|[\\n=]|(\\(\\)))", 1475 | "beginCaptures": { 1476 | "1": { 1477 | "name": "keyword.fsharp" 1478 | }, 1479 | "2": { 1480 | "name": "keyword.fsharp" 1481 | } 1482 | }, 1483 | "endCaptures": { 1484 | "2": { 1485 | "name": "keyword.fsharp" 1486 | }, 1487 | "3": { 1488 | "name": "keyword.fsharp" 1489 | }, 1490 | "4": { 1491 | "name": "keyword.fsharp" 1492 | }, 1493 | "5": { 1494 | "name": "variable.parameter.fsharp" 1495 | }, 1496 | "6": { 1497 | "name": "keyword.symbol.fsharp" 1498 | }, 1499 | "7": { 1500 | "name": "constant.language.unit.fsharp" 1501 | } 1502 | }, 1503 | "patterns": [ 1504 | { 1505 | "include": "#comments" 1506 | }, 1507 | { 1508 | "include": "#attributes" 1509 | }, 1510 | { 1511 | "match": "([[:alpha:]0-9'^._]+|``[[:alpha:]0-9'`^:,._ ]+``)", 1512 | "captures": { 1513 | "1": { 1514 | "name": "entity.name.type.fsharp" 1515 | } 1516 | } 1517 | }, 1518 | { 1519 | "begin": "(<)", 1520 | "end": "((?)", 1521 | "beginCaptures": { 1522 | "1": { 1523 | "name": "keyword.fsharp" 1524 | } 1525 | }, 1526 | "endCaptures": { 1527 | "1": { 1528 | "name": "keyword.fsharp" 1529 | } 1530 | }, 1531 | "patterns": [ 1532 | { 1533 | "match": "(('|\\^)``[[:alpha:]0-9`^:,._ ]+``|('|\\^)[[:alpha:]0-9`^:._]+)", 1534 | "captures": { 1535 | "1": { 1536 | "name": "entity.name.type.fsharp" 1537 | } 1538 | } 1539 | }, 1540 | { 1541 | "name": "keyword.fsharp", 1542 | "match": "\\b(interface|with|abstract|and|when|or|not|struct|equality|comparison|unmanaged|delegate|enum)\\b" 1543 | }, 1544 | { 1545 | "begin": "(\\()", 1546 | "end": "(\\))", 1547 | "beginCaptures": { 1548 | "1": { 1549 | "name": "keyword.symbol.fsharp" 1550 | } 1551 | }, 1552 | "endCaptures": { 1553 | "1": { 1554 | "name": "keyword.symbol.fsharp" 1555 | } 1556 | }, 1557 | "patterns": [ 1558 | { 1559 | "match": "(static member|member|new)", 1560 | "captures": { 1561 | "1": { 1562 | "name": "keyword.fsharp" 1563 | } 1564 | } 1565 | }, 1566 | { 1567 | "include": "#common_binding_definition" 1568 | } 1569 | ] 1570 | }, 1571 | { 1572 | "match": "([\\w0-9'`^._]+)", 1573 | "comments": "Here we need the \\w modifier in order to check that the words isn't blacklisted", 1574 | "captures": { 1575 | "1": { 1576 | "name": "entity.name.type.fsharp" 1577 | } 1578 | } 1579 | }, 1580 | { 1581 | "include": "#keywords" 1582 | } 1583 | ] 1584 | }, 1585 | { 1586 | "match": "\\s*(private|internal|public)", 1587 | "captures": { 1588 | "1": { 1589 | "name": "keyword.symbol.fsharp" 1590 | }, 1591 | "2": { 1592 | "name": "keyword.fsharp" 1593 | } 1594 | } 1595 | }, 1596 | { 1597 | "begin": "(\\()", 1598 | "end": "\\s*(?=(=)|[\\n=]|(\\(\\))|(as))", 1599 | "beginCaptures": { 1600 | "1": { 1601 | "name": "keyword.symbol.fsharp" 1602 | } 1603 | }, 1604 | "endCaptures": { 1605 | "1": { 1606 | "name": "keyword.symbol.fsharp" 1607 | } 1608 | }, 1609 | "patterns": [ 1610 | { 1611 | "include": "#member_declaration" 1612 | } 1613 | ] 1614 | }, 1615 | { 1616 | "include": "#keywords" 1617 | } 1618 | ] 1619 | } 1620 | ] 1621 | }, 1622 | "record_declaration": { 1623 | "patterns": [ 1624 | { 1625 | "begin": "(\\{)", 1626 | "beginCaptures": { 1627 | "1": { 1628 | "name": "keyword.symbol.fsharp" 1629 | } 1630 | }, 1631 | "end": "(?<=\\})", 1632 | "patterns": [ 1633 | { 1634 | "include": "#comments" 1635 | }, 1636 | { 1637 | "begin": "(((mutable)\\s[[:alpha:]]+)|[[:alpha:]0-9'`<>^._]*)\\s*((?