Fetching contributors…
Cannot retrieve contributors at this time
113 lines (72 sloc) 5.06 KB


To build from scratch, install Node.js and run npm install to install development dependencies. GLS is written in TypeScript.

To run end-to-end tests, you'll need the following installed globally:

Python must be available globally as python3. On Windows, you may need to copy & paste python.exe to create an identical python3.exe.

The recommended development setup is Visual Studio Code with the following extensions:

To run a full build+lint+test, run npm run verify.

Use npm run watch to run the TypeScript compiler in watch mode on both source and test files.

Alternately, you can build+lint individual sections of code:

  • npm run src: GLS source code.
  • npm run test: Test file infrastructure.
  • npm run util: Miscellaneous utilities.

The full list of tasks is in package.json.

Style Guidelines

Most rules are enforced by TSLint. For those that aren't, follow the existing conventions, including sensible variable names, consistent indentation, and correct grammar, spelling, and punctuation.


Unit Tests

These are stored under test/unit/**/*.ts and compiled to equivalent files under test/unit/**/*.js.

You can run them with npm run test:unit, or directly with the mocha CLI. Use mocha to specify tests:

mocha test/unit/Tokenization/Parsers/SourceLineParserTests.js
mocha test/unit/Tokenization/Parsers/SourceLineParserTests.js -g "nested CommandNode"

Integration Tests

Test for compiled GLS output are located under test/integration. These integration tests each take in a .gls file, compile it to each supported language, and validate the output is the same as the expected outputs contained in the folder.

Tests are represented by a folder of files, where one file is GLS source code and each other file is how that code should look when compiled to each other language.

Run integration tests with npm run test:integration. You can run a subset of commands by passing -- --include= with a case-insensitive glob to include test names:

npm run test:run:integration -- --include=StringFormat
npm run test:run:integration -- --include=*dictionary* --include=*string*

When adding a new command, always add new integration tests for it.

End-to-End Tests

End-to-end tests are similar to integration tests, but each test folder contains a group of files as a project. Test projects that also contain an output.txt have their "index" (main) files run in each supported language and the console output validated to be the same.

Run integration tests with npm run test:end-to-end. You can run a subset of commands by passing -- --include= with a case-insensitive glob to include test names:

npm run test:run:end-to-end -- --include=Array
npm run test:run:end-to-end -- --include=*array* --include=*list*

When adding a new command or fixing a bug, you should generally add or improve end-to-end tests to cover the change.

Adding Commands

Command class instances are stored at runtime by their unique string name. When adding a new command under src/Commands, also add a line for it under src/CommandsBagFactory.

When adding a new command class, you'll need to override the abstract getMetadata and render commands.

To directly see which files you should add or edit to add a new command, run a full-text search on both the PascalCase command name (e.g. MemberFunction) and the GLS style name (e.g. member function).

(#375 tracks adding a utility to automate adding this!)

"Native" Commands

Some commands, such as native math operations, directly call into native APIs and would require a lot of repeated source code to represent. A NativeCallCommand sub-class of Command can be extended from for these. It requires overriding the abstract retrieveNativeCallSyntax instead of render, which returns the language's NativeCallSyntax for that command.

Adding Languages

Languages are stored at runtime by their language name in a LanguagesBag. You can add a new language by running npm run util:new-language. For example:

npm run util:new-language -- --language-name PHP --language-extension .php --base-name Ruby --base-extension .rb

Files and listings for a new language identical to the original language except for the name and extension will be added locally.