Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional documentation, we greatly value feedback and contributions from our community.
Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution.
We welcome you to use the GitHub issue tracker to report bugs or suggest features.
When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
- A reproducible test case or series of steps
- The version of our code being used
- Any modifications you've made relevant to the bug
- Anything unusual about your environment or deployment
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
- You are working against the latest source on the main branch.
- You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
- You open an issue to discuss any significant work - we would hate for your time to be wasted.
To send us a pull request, please:
- Fork the repository.
- Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
- Ensure local tests pass.
- Commit to your fork using clear commit messages.
- Send us a pull request, answering any default questions in the pull request interface.
- Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
GitHub provides additional document on forking a repository and creating a pull request.
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
This project has adopted the Amazon Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.
See the LICENSE file for our project's licensing. We will ask you to confirm the licensing of your contribution.
node
version 18+npm
- VSCode (recommended)
Run:
git clone [email protected]:aws/language-servers.git
cd language-servers
npm install
When creating new sub-packages, take into account the following naming guidelines:
- If package is intended for publishing and distribution on NPM JS, use
@aws/
prefix. E.g.@aws/<name>
. - If package is not intended to be published, use the
@amzn/
prefix. E.g.@amzn/<name>
npm run compile
Builds are typically incremental. If you need to recompile (for example when you switch branches):
npm run clean
npm run compile
Language servers are built into their own packages (under ./server).
A separate set of packages (under ./app) then instantiate these language servers. These packages are packaged into standalone javascript application servers, with the intention of being integrated into IDEs. Packaging is performed with Webpack. These bundles require nodejs to be installed on the system they are run on. By default, bundles are produced in ./app/**/build/*
directories can be started as node applications, for example:
node ./app/aws-lsp-codewhisperer-binary/aws-lsp-codewhisperer-token-binary.js --stdio
Commit messages merged to main branch must follow Conventional Commits specification format. This is required to ensure readable, standard format of commits history. We also rely on it to setup automation for generating change logs and making releases.
The commit message should be structured as follows:
<type>([optional scope]): <description>
[optional body]
[optional footer(s)]
The header is mandatory and the scope of the header is optional. Examples:
docs: correct spelling of CHANGELOG
feat(amazonq): allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
See more examples at https://www.conventionalcommits.org/en/v1.0.0/#examples.
Type can have one of the following values:
- build: changes to the build system
- chore: any housekeeping changes, which don't fall in other category
- ci: changes to CI script and workflows
- docs: changes to documentation
- feat: a new feature
- fix: a bug fix
- style: visual-only changes, not impacting functionality
- refactor: refactorings not impacting functionality, which are not features or bug fixes
- perf: changes that improve performance of code
- test: adding or fixing tests
The scope should indicate a package, affected by the change. List of support scopes, and corresponding packages:
- amazonq:
./server/aws-lsp-codewhisperer
- chat-client:
./chat-client
- identity:
./server/aws-lsp-identity
- notification:
./server/aws-lsp-notification
- partiql:
./server/aws-lsp-partiql
- release: do not use manually - special scope, reserved for release automation
Empty scopes are allowed, and can be used for cases when change is not related to any particular package, e.g. for ci:
or docs:
One or more footers may be provided one blank line after the body.
Breaking Change must start with BREAKING CHANGE:
words, following with description of the breaking change.
The commit contains the following structural elements, to communicate intent to the consumers of your library:
- fix: a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning).
- feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning).
- BREAKING CHANGE: a commit that has a footer
BREAKING CHANGE:
, or appends a!
after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type.
These rules are used by our automation workflows to collect change logs, and to compute next Semantic Version of packages, impacted by commit.
Since this repository is a shared shared monorepo with many packages, be careful when introducing changes impacting several packages. Extra care should be given when using version-impacting types (especially BREAKING CHANGE).
NOTE: Ensure your VSCode workspace is the root folder or else certain functionality may not work.
This repo contains a minimal vscode client that can be used to easily run and debug changes to this language server.
- Run
npm run package
in the root folder - Set the breakpoints you need, make sure to set them in node_modules, e.g.: to set a breakpoint in the package
aws-lsp-codewhisperer
, set it in the symlinkednode_modules/@aws/lsp-codewhisperer
, not inserver/aws-lsp-codewhisperer
. - Make sure that the preLaunchTask option (for the configuration you are running in
.vscode/launch.json
) is either not set or set towatch
, notcompile
. - In the
Run & Debug
menu, run"Launch as VSCode Extension + Debugging"
. Make sure this is launching the server you wish to use, look at the launch configuration. Keep theAttach to AWS Documents Language Server
to use the debugger. - When the debugging is launched, select the
Attach to AWS Documents Language Server
option from the drop down menu (close to pause/stop buttons). - (Optional) in the activation file you can swap
--inspect
with--inspect-brk
if you need to debug immediately when the node process starts. Read more about it on this site
The VSCode Toolkit Extension can start the AWS Documents Language Server itself. This will explain how to setup the extension to run with the language server and be able to debug it all.
-
Clone the
language-servers
repo:git clone [email protected]:aws/language-servers.git cd language-servers
-
Run:
npm install npm run watch
-
Start the extension in
Run & Debug
using the"Hello World"
launch config. A new window will open.
- In the
Run & Debug
menu, run"CodeWhisperer Server"
- Set breakpoints in
src
where needed - Check the logs in
"AWS Documents Language Server"
output window.
NOTE: If you see "Recommendation failure: Error: Authorization failed, bearer token is not set" errors, make sure to authenticate using
"AWS LSP - Obtain bearer token and send to LSP server"
command.
NOTE: The lsp client is activated by one of the
activationEvents
defined here, the lsp client then starts the LSP server.
Using other clients can also be done with the bundle created from this package.
- Produce a local server bundle
npm run package
. Theapp/
folder contains the configuration of server(s) and it's runtime(s). - Take note of the bundle you wish to use. For this example we will use
app/aws-lsp-codewhisperer-runtimes/out/token-standalone.js
. - Run the bundle using these args
node --inspect=6012 {rootPath}/app/aws-lsp-codewhisperer-runtimes/out/token-standalone.js --nolazy --preserve-symlinks --stdio --pre-init-encryption --set-credentials-encryption-key
or adjust as needed. Refer to the activation file. NOTE: make sure that --inspect or --inspect-brk args are passed right after thenode
command - Attach the debugger you wish to use to the node process. Example in Visual Studio here
npm test
-
The modules used in testing are:
mocha
: Testing frameworkchai
: For assertionssinon
: stub/mock/spy
-
The design of the source code is written with dependency injection in mind. _ An object or function receives other objects or functions for functionality that it depends on, instead of all functionality existing statically in one place. _ This simplifies testing and influences how tests are to be written.
sinon
is a module that allows you to create spies, stubs and mocks.
These are the core components that complement the testing of a dependency injection designed project.
The following is a quick summary of how to use sinon
in this project.
Summary:
// Use to stub interfaces (must explicitly set type in declaration)
stubInterface()
stub(new MyClass()) // Use to stub objects
stub(myFunc) // Use to stub functions
// Explicitly typing
let myClassStub: SinonStubbedInstance<MyClass>
// vs
let myClassStub: MyClass
// will have an impact on compilation and method completion
Imports:
import { stubInterface } from 'ts-sinon' // Only use this module for `stubInterface`
import { SinonStubbedInstance, SinonStubbedMember, createStubInstance, stub } from 'sinon'
Object Instance Stub:
let myClassStub: SinonStubbedInstance<MyClass> = stub(new MyClass())
// Do this if you want myFunc() to execute its actual functionality
myClassStub.myFunc.callThrough()
// Or if you plan to only explicitly stub return values
// it is safer/easier to do the following.
// Note we are not creating a new instance of MyClass here.
let myClassStub: SinonStubbedInstance<MyClass> = createStubInstance(MyClass)
myClassStub.myFunc.returns(3)
Interface Stub:
// Note the need for `ts-sinon.stubInterface()` to stub interfaces.
// `sinon` does not provide the ability to stub interfaces.
let myInterfaceStub: SinonStubbedInstance<MyInterface> = stubInterface()
myInterfaceStub.someFunctionItDefined.returns('my value')
Function Stub:
interface myFuncInterface {
(x: string): string
}
myFunc: myFuncInterface = (x: string) => {
return x
}
// Note `SinonStubedMember` instead of `SinonStubbedInstance` for functions
const myFuncStub: SinonStubbedMember<myFuncI> = stub(myFunc)
// Must explicitly type with `SinonStubbedMember` on assignment for this to pass linting
myFuncStub.callThrough()
Resetting callThrough()
:
If you use callThrough()
on a stubbed object and then want to have it return
a custom value with returns()
. You must first call resetBehaviour()
, then returns()
will work.
const myStubbedFunc = stub()
myStubbedFunc.callThrough()
myStubbedFunc.resetBehaviour()
myStubbedFunc.returns()
- Change the setting
awsDocuments.trace.server
to"verbose"
. This shows all communication between the client and server. - In the top left menu bar:
View > Output
- Select
"AWS Documents Language Server"
from the dropdown menu in the topright.
Language servers developed in this package can be built for different runtimes developed in Language Server Runtimes project.
Language Server Runtimes
provides a set of interfaces and constructs that can be used to inject cross-platform implementations of features, reused across language servers. Using runtime constructs, Language Servers could be built and packages into artifact of different formats: standalone bundle formats as explained earlier in this document, or packages as Javascript Webworker bundle.
This Language Servers repository includes set of packages, which demonstrate how to build Language server together with specific runtime. See Building the Repo section in this guide.
Sometimes there is a need to build and develop both Language Servers with Language Server Runtimes projects. Since language-server-runtimes
is used as an npm dependency, it can be developed using npm link
in this repo.
-
Clone the
language-servers
and thelanguage-server-runtimes
repos:git clone [email protected]:aws/language-servers.git git clone [email protected]:aws/language-server-runtimes.git
-
Install dependencies in
language-server-runtimes
folder. Createnpm link
for it, if you plan to modify it for development and testing purposes.
Note: Since v0.2.3, we need to create a link to /language-server-runtimes/runtimes/out
directory, due to monorepo structure of language-server-runtimes
project.
```bash
cd language-server-runtimes && npm install && cd ./runtimes && npm run prepub && cd ./out && npm link
```
-
Install dependencies in
language-servers
folder:cd ../language-servers && npm install
-
Use npm link to
language-server-runtimes
:npm link @aws/language-server-runtimes
-
Build server bundles:
npm run package
Using local checkout of language-server-runtimes
you can iterate or experiment with both projects and produce working language server builds locally. Built servers can be found in ./app/**/build
folder.
Doesn’t seem like language-servers is using your local language-server-runtimes install? Try the extreme option:
# From language-server-runtimes
npm run clean &&
npm install &&
npm -ws install &&
npm run compile &&
npm -ws run prepub --if-present
# From language-servers
npm run clean &&
rm -fr node_modules &&
rm -fr server/aws-lsp-codewhisperer/node_modules
npm install &&
npm -ws install &&
npm link @aws/language-server-runtimes @aws/language-server-runtimes-types &&
npm run compile -- --force