FsAutoComplete (FSAC) is a Language Server Protocol (LSP) backend service that provides rich editing and intellisense features for F# development. It serves as the core engine behind F# support in various editors including Visual Studio Code (Ionide), Emacs, Neovim, Vim, Sublime Text, and Zed.
FsAutoComplete currently provides F# support for:
- Visual Studio Code (via Ionide)
- Emacs (via emacs-fsharp-mode)
- Neovim (via nvim-lspconfig)
- Vim (via vim-fsharp)
- Sublime Text (via LSP package)
- Zed (via zed-fsharp)
-
FsAutoComplete.Core: Contains the core functionality, including:
- F# compiler service interfaces
- Code generation and refactoring utilities
- Symbol resolution and type checking
- Signature formatting and documentation
- File system abstractions
-
FsAutoComplete: Main LSP server implementation with:
- LSP protocol handlers and endpoints
- Code fixes and quick actions
- Parser for LSP requests/responses
- Program entry point
-
FsAutoComplete.Logging: Centralized logging infrastructure
- FSharp.Compiler.Service (>= 43.9.300): Core F# compiler APIs for language analysis
- Ionide.ProjInfo (>= 0.71.2): Project and solution file parsing, with separate packages for FCS integration and project system
- FSharpLint.Core: Code linting and static analysis
- Fantomas.Client (>= 0.9): F# code formatting
- Microsoft.Build (>= 17.2): MSBuild integration for project loading
- Serilog (>= 2.10.0): Structured logging infrastructure
- Language Server Protocol: Communication with editors
- netstandard2.0 & netstandard2.1: For broader compatibility
- net8.0 & net9.0: For latest .NET features and performance
Requirements:
- .NET SDK (see
global.jsonfor exact version - minimum >= 6.0, recommended >= 7.0)
# Restore .NET tools (including Paket)
dotnet tool restore
# Build the entire solution
dotnet build
# Run tests
dotnet test
# Run specific test project
dotnet test -f net8.0 ./test/FsAutoComplete.Tests.Lsp/FsAutoComplete.Tests.Lsp.fsproj
# Format code
dotnet fantomas src/ test/- DevContainer: Use with VSCode's Remote Containers extension for stable development environment
- Gitpod: Web-based VSCode IDE available at https://gitpod.io/#https://github.com/fsharp/fsautocomplete
This project uses Paket for dependency management instead of NuGet directly:
- Dependencies are declared in
paket.dependencies - Lock file is
paket.lock - Each project has its own
paket.referencesfile
- Located in
src/FsAutoComplete/CodeFixes/ - Each code fix is typically a separate F# module
- Follow the pattern: analyze issue → generate fix → apply transformation
- Scaffolding: Use
dotnet fsi build.fsx -- -p ScaffoldCodeFix YourCodeFixNameto create new code fixes - This generates implementation file, signature file, and unit test, plus updates registration files
- Examples include:
ImplementInterface.fs,GenerateUnionCases.fs,AddMissingEqualsToTypeDefinition.fs
- Standard LSP endpoints in
src/FsAutoComplete/LspServers/ - Key server files:
AdaptiveFSharpLspServer.fs,AdaptiveServerState.fs,ProjectWorkspace.fs - Custom F#-specific endpoints prefixed with
fsharp/ - Request/response types in
CommandResponse.fs - Interface definitions in
IFSharpLspServer.fs
- Main test suite in
test/FsAutoComplete.Tests.Lsp/ - Tests organized by feature area (CompletionTests, CodeFixTests, etc.)
- Uses F# testing frameworks with custom helpers in
Helpers.fs - Test cases often in
TestCases/subdirectories
- Follow F# community conventions
- Use
fantomasfor code formatting (configured in the project) - Prefer immutable data structures and functional programming patterns
- Use explicit type annotations where they improve clarity
- One primary type/feature per file
- Use
.fsand.fsipairs for public APIs - Organize related functionality into modules
- Follow naming conventions:
CamelCasefor types,camelCasefor values
- Use F# Result types for error handling where appropriate
- Use FsToolkit.ErrorHandling for railway-oriented programming
- Prefer explicit error types over generic exceptions
textDocument/completionwithcompletionItem/resolvetextDocument/hover,textDocument/definition,textDocument/referencestextDocument/codeAction,textDocument/codeLenstextDocument/formatting(via Fantomas)textDocument/rename,textDocument/signatureHelp- Workspace management and file watching
fsharp/signature: Get formatted signature at positionfsharp/compile: Compile project and return diagnosticsfsharp/workspacePeek: Discover available projects/solutionsfsharp/workspaceLoad: Load specific projectsfsproj/addFile,fsproj/removeFile: Project file manipulationfsharp/documentationForSymbol: Get documentation for symbolsfsharp/f1Help: F1 help functionalityfsharp/fsi: F# Interactive integration
- Tests are organized by feature area
- Use descriptive test names that explain the scenario
- Include both positive and negative test cases
- Test with realistic F# code examples
- Identify the appropriate test file (e.g.,
CompletionTests.fsfor completion features) - Follow existing patterns for test setup and assertions
- Use the helpers in
Helpers.fsfor common operations - Include edge cases and error conditions
- For code fixes: Run focused tests with
dotnet run -f net8.0 --project ./test/FsAutoComplete.Tests.Lsp/FsAutoComplete.Tests.Lsp.fsproj - Remove focused test markers before submitting PRs (they cause CI failures)
- Do not delete tests without permission.
- Sample F# projects in
TestCases/directories - Use minimal, focused examples that demonstrate specific features
- Avoid overly complex test scenarios that are hard to debug
- Be mindful of memory usage in long-running language server scenarios
- Dispose of compiler service resources appropriately
- Use caching judiciously to balance performance and memory
- LSP operations should be fast and non-blocking
- Use async/await patterns for I/O operations
- Consider cancellation tokens for long-running operations
- Tracing is available with
--otel-exporter-enabledflag - Use Jaeger for trace visualization during development
- Activity tracing helps debug performance issues
- Structured logging via Serilog
- Use appropriate log levels (Debug, Info, Warning, Error)
- Include relevant context in log messages
- Always work with
FSharpCheckFileResultsandFSharpParseFileResults - Handle both parsed and typed ASTs appropriately
- Be aware of file dependencies and project context
- Validate input parameters
- Handle exceptions gracefully
- Return appropriate error responses for invalid requests
- Use proper JSON serialization
- Use the F# AST utilities in
TypedAstUtils.fsandUntypedAstUtils.fs - Consider both syntactic and semantic correctness
- Test generated code compiles and has expected behavior
- Ensure all tests pass:
dotnet test - Run code formatting:
dotnet fantomas src/ test/ - ALWAYS add test cases for changes, run them and report results in PRs
- Verify the solution builds cleanly
- Test your changes with a real F# project if possible
- Correctness of F# language analysis
- Performance impact on language server operations
- Compatibility with different F# project types
- LSP protocol compliance
- Test coverage for new features
- FSharpLint - Static analysis tool
- Paket - Dependency management
- FAKE - Build automation (used for scaffolding)