Skip to content

Latest commit

 

History

History
222 lines (158 loc) · 13.2 KB

CONTRIBUTING.md

File metadata and controls

222 lines (158 loc) · 13.2 KB

Contributing 👥

The fish-lsp aims to create an experience that aligns with the fish language goals.

In a quick overview, the project hopes to create a development environment that is as friendly as possible.

Thanks for the interest in contributing to the project 🙏


There are many ways to contribute to the project:

  • Submit bugs, and help work on fixes
  • Refactor out unnecessary source code
  • Implement features, outlined in the roadmap.
  • Implement new client configurations, outlined in this repo
  • Add tests to verify expected behavior.
  • Update documentation, across any of the project's repositories

Getting started 🚀

  1. Begin by forking the project, then build your local fork 🗃️.

  2. Once you have installed the local fork of the project (i.e., you have a successfully compiled fish-lsp executable, and have a working client configuration), you can then begin testing locally 📝.

  3. Upon completing a change, submit a PR 🎉.

Places to Start 🏁

Note

Browsing both wiki/sources#vscode-extensions-examples and ROADMAP are the easiest method for understanding how to create future fish-lsp feature's

Helpful Workflows ⌛

Test Driven Development Workflow 🐣

Since stdin/stdout are reserved for the protocol to communicate, a generally successful method to achieve quick results, is through TDD (Test Driven Development). Many tree-sitter helper functions (tree-sitter.ts, and node-types.ts) have already been written, to aid in providing useful functionality for generic support of any possible combination need for future types.

Having said that, if you a need for a new definition in tree-sitter.ts or node-types.ts comes up, adding it to the proper file is fine (tree-sitter.ts generally deals with movement or interacting with a SyntaxNode[] | Tree, where as node-types.ts generally deals with filter functions that can determine what type of SyntaxNode is passed into it). The only requirement is that you will for new additions to these files, is that you include proper tests in their corresponding test-data/{node-types,tree-sitter}.test.ts)

Sceenshot

Integration Testing Workflow 🤯

Test directly in the client of your choosing. This is a more difficult to setup, but could be helpful if you are testing specific behaviors like the interacting with fish-lsp's environment variables, configuration options, handler testing or other more specific tasks.

Screenshot

How to Build using these Workflows 🏗️

  1. Pull up some Documentation 🔬

    • lsif - The official Language Server Protocol specification
    • wiki/sources - Sources that are similar to this project
    • roadmap - Ideas/Documentation for future plans
  2. Create a file in the test-data/ directory 👷

    • START WITH VERY BASIC EXAMPLES!!! Pure functions are your friend
    • Checkout ./test-data/helpers.ts, setLogger() which is provided for logging tests
    • Test your FILE.test.ts with command: yarn test FILE --watchAll
    • Feel free to overwrite any existing test-file that is not in the package.json key test-hook
    • Use import { initializeParser } from '../src/parser for building SyntaxNode[] composite object arrays (aka trees).
  3. Iteratively continue improving your feature ♾️

    • Once you have a feature's hard coded input & outputs working as expected, you can begin trying to impalement it as an actual server.handler

    • You can try adding logging to your feature's specific handlerParams, to get an exact example of it's shape. (This is the premise outlined via: integration testing workflow)

      # display the logs
      tail -f $(fish-lsp info --logs-file)
    • Alternatively, you can mock the data-type from the vscode-languageserver or refer to the same documentation on lsif

  4. Add your feature to a server.ts handler 🤝

    • Document your handler, if necessary.
    • Feel free to submit your server handler in separate working release stages, instead of trying to build entire feature's independently. (i.e., if your CodeAction's only support a singular CodeActionType)
    • Submit your PR 🍾

Helpful Topics and Concepts 📚

Currying is a useful design pattern, that makes iterating through the Abstract Syntax Trees (ASTs) significantly less error prone.

Note

While it is still not entirely perfect, errors that appear to be caused by inconsistencies in our node-types.ts functors are more likely to be caused by the earlier language server protocol versions requirement for our Nodes in our tree items, to be stored as a flat list.

Due to this reason, the project has undergone a significant rewrite of previously working features (diagnostics, etc...). Working on reintroducing the disabled features would be a great place to start, as many of server providers were implemented using range based location calculation's to abide to their prior protocol use.

Relevant examples for each of the feature's mentioned above are included @ wiki/sources

Child process execution via sub-shells. Sub-shell environment's are extensively relied on throughout the code base.

Markdown formatting syntax, and nested language support via triple backticks.

Asynchronous processes and race conditions. Especially during src/server.ts startup.

Prefetching relevant information and caching it for global use.

Important Tooling Provided 🧰

  • tree-sitter - used for data structures/algorithms, prevalent to the shell language.

    • yarn sh:build-wasm - should handle building the wasm file
    • @esdmr/[email protected] - handles installing the actual tree-sitter-fish.wasm package
    • web-tree-sitter - is the API for SyntaxNode[], Parser, Range, etc...
  • eslint - used for linting and formatting

    • yarn lint - lint and fix the current project (husky pre-push hook)
    • yarn lint:verbose - lint, and display output
  • knip - used for tree-shaking and checking unused dependencies

    • yarn refactacor - package.json script to run knip
    • You can refactor major sections of unused code of out the project easily with this command
  • commander.js - used for src/cli.ts and other tooling to start the server

  • zod - parses the env into a typesafe object

    • handles parsing the fish_lsp* variables in our node process.env object
    • builds the result object in the global variable config
  • vscode-languageserver - the SPEC for defining our LSP.

    • Objects & Interfaces specific to fish-lsp typically extend this base specification
    • Type Definitions useful for handler's are defined throughout this package
  • husky - the git-hooks for interacting with project's source code

    • lints the project on-push
    • removes dependencies before commit pre-commit
    • initializes yarn post-merge
  • jest - testing the project

    • relevant locations: test-data/*.test.ts, jest.config.js && tsconfig.test.json
    • yarn test-hook is a future supported feature, for specifying individual test files to opt into successful reporting for master branch (via git action).
    • yarn test someFile.test.ts --watchAll is the designated method for watching a test's changes

Other Noteworthy Tooling 🛠️

Becoming familiar with using the src/utils/{tree-sitter,node-types}.ts code, is significantly easier while using the previously mentioned TDD Workflow.

Using an equivalent tree-sitter visualization command to neovim's command, :InspectEdit is also highly recommended. If you are unsure what this command does, it essentially allows you to visualize the AST that tree-sitter parsed from fish input. Using this while writing test files, significantly improves the overall testing experience.

Also don't forget to make use of the fish-lsp --flags! There is plenty of use cases the binary supports, like:
fish-lsp env --create, fish-lsp complete, fish-lsp info --logs-file,
fish-lsp info --time, fish-lsp url --sources, fish-lsp logger --show, + more...

Adding New Language Clients 📈

Generally, all that is required is using the fish-lsp start command, and specifying fish for attaching the server to a filetype. Any other fluff in this settings, as seen in the JSON example, is only for ease of use.

Adding new client configurations, to the fish-lsp-client's repo, is greatly appreciated!

Contributing Github Actions ♻️

If you're trying to add a new github action to the project, please take a close look at the scripts/* directory, along with package.json.

A github action that uses that compiles the project, requires fish to be installed and setup, before yarn in the action.

The current workflow actions, are the best place to see how this is achieved.

Got helpful scripts? 🛂

Show & tell is a helpful place to document your useful configurations for working on the fish-lsp.

Displaying demos, features and other cool discoveries are also welcome :)