├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── .vscodeignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── COPYRIGHT ├── LICENSE.md ├── README.md ├── icon.png ├── language-configuration.json ├── package-lock.json ├── package.json ├── src ├── client.ts ├── config.ts └── main.ts ├── syntaxes └── mun.tmGrammar.json └── tsconfig.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "es6": true, 4 | "node": true, 5 | }, 6 | "parser": "@typescript-eslint/parser", 7 | "parserOptions": { 8 | "project": "tsconfig.json", 9 | "sourceType": "module" 10 | }, 11 | "plugins": [ 12 | "@typescript-eslint" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [pull_request, push] 4 | 5 | concurrency: 6 | group: ${{ github.workflow }}-${{ github.ref }} 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | typescript: 11 | name: TypeScript 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [ubuntu-latest, windows-latest, macos-latest] 16 | 17 | runs-on: ${{ matrix.os }} 18 | 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v2 22 | 23 | - name: Install Nodejs 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: 16.x 27 | 28 | - run: npm ci 29 | 30 | - run: npm run lint 31 | 32 | - run: npm run package --scripts-prepend-node-path 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | *.vsix 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Run VSCode Extension", 9 | "type": "extensionHost", 10 | "request": "launch", 11 | "runtimeExecutable": "${execPath}", 12 | "args": [ 13 | "--disable-extensions", 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/dist/**/*.js" 18 | ], 19 | "preLaunchTask": "Build VSCode Extension", 20 | "skipFiles": [ 21 | "/**/*.js" 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Build VSCode Extension in Background", 8 | "group": "build", 9 | "type": "npm", 10 | "script": "watch", 11 | "problemMatcher": { 12 | "base": "$tsc-watch", 13 | "fileLocation": ["${workspaceFolder}"] 14 | }, 15 | "isBackground": true, 16 | }, 17 | { 18 | "label": "Build VSCode Extension", 19 | "group": "build", 20 | "type": "npm", 21 | "script": "build", 22 | "problemMatcher": { 23 | "base": "$tsc", 24 | "fileLocation": ["${workspaceFolder}"] 25 | }, 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | ** 2 | !dist/main.js 3 | !package-lock.json 4 | !package.json 5 | !README.md 6 | !LICENSE.md 7 | !syntaxes/mun.tmGrammar.json 8 | !language-configuration.json 9 | !icon.png 10 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Mun Programming Language Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | These are the policies for upholding our community's standards of conduct. If 41 | you feel that a thread needs moderation, please contact the Mun moderators at 42 | [moderators@mun-lang.org](mailto:moderators@mun-lang.org). 43 | 44 | 1. Remarks that violate the Mun standards of conduct, including hateful, 45 | hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing in 46 | general is discouraged, and never tolerated if targeting another user, and 47 | never in a hateful manner.) 48 | 2. Remarks that moderators find inappropriate, whether listed in the code of 49 | conduct or not, are also not allowed. 50 | 3. Moderators will first respond to such remarks with a warning. 51 | 4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of 52 | the communication channel to cool off. 53 | 5. If the user comes back and continues to make trouble, they will be banned, 54 | i.e., indefinitely excluded. 55 | 6. Moderators may choose at their discretion to un-ban the user if it was a 56 | first offense and they offer the offended party a genuine apology. 57 | 7. If a moderator bans someone and you think it was unjustified, please take it 58 | up with that moderator, or with a different moderator, **in private**. 59 | Complaints about bans in-channel are not allowed. 60 | 8. Moderators, organization members, and anyone closely involved with the 61 | Mun project are held to a higher standard than other community members. 62 | If a moderator creates an inappropriate situation, they should expect less 63 | leeway than others. 64 | 65 | ## Goals 66 | 67 | In the Mun community we strive to go the extra step to look out for each other. 68 | Don't just aim to be technically unimpeachable, try to be your best self. In 69 | particular, avoid flirting with offensive or sensitive issues, particularly if 70 | they're off-topic; this all too often leads to unnecessary fights, hurt 71 | feelings, and damaged trust; worse, it can drive people away from the community 72 | entirely. 73 | 74 | And if someone takes issue with something you said or did, resist the urge to be 75 | defensive. Just stop doing what it was they complained about and apologize. Even 76 | if you feel you were misinterpreted or unfairly accused, chances are good there 77 | was something you could've communicated better — remember that it's your 78 | responsibility to make your fellow Mun community members comfortable. Everyone 79 | wants to get along and we are all here first and foremost because we want to 80 | talk about making games. You will find that people will be eager to assume good 81 | intent and forgive as long as you earn their trust. 82 | 83 | ## Scope 84 | 85 | This Code of Conduct applies both within project spaces and in public spaces 86 | when an individual is representing the project or its community. Examples of 87 | representing a project or community include using an official project e-mail 88 | address, posting via an official social media account, or acting as an appointed 89 | representative at an online or offline event. Representation of a project may be 90 | further defined and clarified by project maintainers. 91 | 92 | ## Enforcement 93 | 94 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 95 | reported by contacting the project team at 96 | [moderators@mun-lang.org](mailto:moderators@mun-lang.org). All complaints will 97 | be reviewed and investigated and will result in a response that is deemed 98 | necessary and appropriate to the circumstances. The project team is obligated to 99 | maintain confidentiality with regard to the reporter of an incident. Further 100 | details of specific enforcement policies may be posted separately. 101 | 102 | Project maintainers who do not follow or enforce the Code of Conduct in good 103 | faith may face temporary or permanent repercussions as determined by other 104 | members of the project's leadership. 105 | 106 | ## Attribution 107 | 108 | This Code of Conduct is adapted from the [Contributor 109 | Covenant][https://www.contributor-covenant.org], version 1.4, available at 110 | https://www.contributor-covenant.org/version/1/4/code-of-conduct.html and the 111 | Rust Code of Conduct, available here: https://www.rust-lang.org/conduct.html. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Mun 2 | 3 | Ah! Good to see you are reading this. We feel that developing a programming 4 | language without the input of our target audience is counterproductive. Therefore 5 | we gladly welcome contributions from all developers! 6 | 7 | If you haven't already, [join our discord server](https://discord.gg/SfvvcCU). We can help you get underway with the things you're most excited about. 8 | 9 | Some important resources to get started are: 10 | 11 | - [Our roadmap](https://trello.com/b/ZcMiREnC/mun-roadmap) gives a very broad 12 | overview of where we're heading. 13 | - We're usually online on [our discord server](https://discord.gg/SfvvcCU) 14 | during business hours (UTC+1). 15 | - Bugs? [Report them on GitHub](https://github.com/mun-lang/mun/issues) 16 | - What is our vision on [testing](#testing)? 17 | - Try to use [Test Driven Development](#test-driven-development) 18 | - About [snapshot tests](#snapshot-tests) 19 | - How to [submit changes](#submitting-changes)? 20 | - Writing [commit messages](#commit-message-format) 21 | 22 | ## Testing 23 | 24 | We feel that having an extensive [regression 25 | testing](https://en.wikipedia.org/wiki/Regression_testing) suite allows 26 | developers to add new features or change existing features with more confidence; 27 | knowing that changes behave the way you expect them to and without unwittingly 28 | impacting other features. 29 | 30 | ### Test Driven Development 31 | 32 | We try to implement new features using [Test Driven Development 33 | (TTD)](https://en.wikipedia.org/wiki/Test-driven_development). In practice this 34 | means that we write tests - based on requirements - before implementing new features to ensure 35 | that they work. This seamlessly integrates with regression testing, as 36 | there is no extra workload. 37 | 38 | ### Snapshot tests 39 | 40 | A snapshot test asserts that the output of an operation doesn't change. As such, we use it to verify that a feature generates (and keeps 41 | generating) the correct output. The [insta crate](https://crates.io/crates/insta) is 42 | used throughout the codebase to enable this functionality. See 43 | [crates/mun_hir/src/ty/tests.rs](crates/mun_hir/src/ty/tests.rs) for an example. 44 | 45 | ## Submitting changes 46 | 47 | Please submit a [GitHub Pull Request to 48 | mun-lang/mun](https://github.com/mun-lang/mun/pull/new/master) with a clear list 49 | of changes (read more about [pull 50 | requests](http://help.github.com/pull-requests/)). When you submit a pull request, 51 | make sure to include tests that validate the implemented feature or bugfix 52 | ([read about testing in Mun](testing)). Before committing, please confirm that your code 53 | style is correct (using `cargo fmt`) and all lint warning have been resolved 54 | (using `cargo clippy`). We integrated [cargo-husky](https://github.com/rhysd/cargo-husky) 55 | as a pre-commit hook, to make this process as simple as possible. 56 | 57 | ### Commit message format 58 | 59 | Always write a clear log message for your commits. We use the [Conventional 60 | Commits](https://www.conventionalcommits.org/) format, which states that a commit 61 | message should be structured as follows: 62 | 63 | ``` 64 | [optional scope]: 65 | 66 | [optional body] 67 | 68 | [optional footer(s)] 69 | ``` 70 | 71 | BREAKING CHANGE: a commit that has a footer BREAKING CHANGE:, or appends a ! 72 | after the type/scope, introduces a breaking API change (correlating with MAJOR 73 | in semantic versioning). A BREAKING CHANGE can be part of commits of any type. 74 | 75 | Recommended *type*s are: `feat`, `fix`, `ci`, `docs`, `style`, `refactor`, 76 | `perf`, `test`, `revert` or `improvement`. 77 | 78 | One-line messages are fine for small changes, but bigger changes should include 79 | a body. 80 | 81 | #### Examples 82 | 83 | ``` 84 | feat: allow provided config object to extend other configs 85 | ``` 86 | ``` 87 | refactor!: drop support for Node 6 88 | ``` 89 | ``` 90 | feat(lang): add polish language 91 | ``` 92 | ``` 93 | fix: correct minor typos in code 94 | 95 | see the issue for details 96 | 97 | on typos fixed. 98 | 99 | Reviewed-by: Z 100 | Refs #133 101 | ``` 102 | 103 | For more examples, check [recent commit 104 | message](https://github.com/mun-lang/mun/commits/master). 105 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright 2019 The Mun Development Team 2 | 3 | Licensed under the PolyForm Noncommercial license, Version 1.0.0, . 4 | 5 | 6 | This file may not be copied, modified, or distributed except according to those terms. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Note: Mun VS Code Extension is free to use for all, including commercial users, until v1.0.0 is released. After v1.0.0, commercial users must contact team@mun-lang.org to purchase a Commercial-use license. 2 | 3 | # PolyForm Noncommercial License 1.0.0 4 | 5 | 6 | 7 | ## Acceptance 8 | 9 | In order to get any license under these terms, you must agree 10 | to them as both strict obligations and conditions to all 11 | your licenses. 12 | 13 | ## Copyright License 14 | 15 | The licensor grants you a copyright license for the 16 | software to do everything you might do with the software 17 | that would otherwise infringe the licensor's copyright 18 | in it for any permitted purpose. However, you may 19 | only distribute the software according to [Distribution 20 | License](#distribution-license) and make changes or new works 21 | based on the software according to [Changes and New Works 22 | License](#changes-and-new-works-license). 23 | 24 | ## Distribution License 25 | 26 | The licensor grants you an additional copyright license 27 | to distribute copies of the software. Your license 28 | to distribute covers distributing the software with 29 | changes and new works permitted by [Changes and New Works 30 | License](#changes-and-new-works-license). 31 | 32 | ## Notices 33 | 34 | You must ensure that anyone who gets a copy of any part of 35 | the software from you also gets a copy of these terms or the 36 | URL for them above, as well as copies of any plain-text lines 37 | beginning with `Required Notice:` that the licensor provided 38 | with the software. For example: 39 | 40 | > Required Notice: Copyright Yoyodyne, Inc. (http://example.com) 41 | 42 | ## Changes and New Works License 43 | 44 | The licensor grants you an additional copyright license to 45 | make changes and new works based on the software for any 46 | permitted purpose. 47 | 48 | ## Patent License 49 | 50 | The licensor grants you a patent license for the software that 51 | covers patent claims the licensor can license, or becomes able 52 | to license, that you would infringe by using the software. 53 | 54 | ## Noncommercial Purposes 55 | 56 | Any noncommercial purpose is a permitted purpose. 57 | 58 | ## Personal Uses 59 | 60 | Personal use for research, experiment, and testing for 61 | the benefit of public knowledge, personal study, private 62 | entertainment, hobby projects, amateur pursuits, or religious 63 | observance, without any anticipated commercial application, 64 | is use for a permitted purpose. 65 | 66 | ## Noncommercial Organizations 67 | 68 | Use by any charitable organization, educational institution, 69 | public research organization, public safety or health 70 | organization, environmental protection organization, 71 | or government institution is use for a permitted purpose 72 | regardless of the source of funding or obligations resulting 73 | from the funding. 74 | 75 | ## Fair Use 76 | 77 | You may have "fair use" rights for the software under the 78 | law. These terms do not limit them. 79 | 80 | ## No Other Rights 81 | 82 | These terms do not allow you to sublicense or transfer any of 83 | your licenses to anyone else, or prevent the licensor from 84 | granting licenses to anyone else. These terms do not imply 85 | any other licenses. 86 | 87 | ## Patent Defense 88 | 89 | If you make any written claim that the software infringes or 90 | contributes to infringement of any patent, your patent license 91 | for the software granted under these terms ends immediately. If 92 | your company makes such a claim, your patent license ends 93 | immediately for work on behalf of your company. 94 | 95 | ## Violations 96 | 97 | The first time you are notified in writing that you have 98 | violated any of these terms, or done anything with the software 99 | not covered by your licenses, your licenses can nonetheless 100 | continue if you come into full compliance with these terms, 101 | and take practical steps to correct past violations, within 102 | 32 days of receiving notice. Otherwise, all your licenses 103 | end immediately. 104 | 105 | ## No Liability 106 | 107 | ***As far as the law allows, the software comes as is, without 108 | any warranty or condition, and the licensor will not be liable 109 | to you for any damages arising out of these terms or the use 110 | or nature of the software, under any kind of legal claim.*** 111 | 112 | ## Definitions 113 | 114 | The **licensor** is the individual or entity offering these 115 | terms, and the **software** is the software the licensor makes 116 | available under these terms. 117 | 118 | **You** refers to the individual or entity agreeing to these 119 | terms. 120 | 121 | **Your company** is any legal entity, sole proprietorship, 122 | or other kind of organization that you work for, plus all 123 | organizations that have control over, are under the control of, 124 | or are under common control with that organization. **Control** 125 | means ownership of substantially all the assets of an entity, 126 | or the power to direct its management and policies by vote, 127 | contract, or otherwise. Control can be direct or indirect. 128 | 129 | **Your licenses** are all the licenses granted to you for the 130 | software under these terms. 131 | 132 | **Use** means anything you do with the software requiring one 133 | of your licenses. 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mun 2 | 3 | [![Visual Studio Marketplace][marketplace-badge]][marketplace] 4 | [![MIT/Apache][licence-badge]][license] 5 | [![Join us on Discord][discord-badge]][discord] 6 | 7 | [licence-badge]: https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue 8 | [license]: COPYRIGHT 9 | 10 | [discord-badge]: https://img.shields.io/discord/602227728480993281.svg?logo=discord 11 | [discord]: https://discord.gg/SfvvcCU 12 | 13 | [marketplace-badge]: https://img.shields.io/visual-studio-marketplace/v/mun-lang.mun 14 | [marketplace]: https://marketplace.visualstudio.com/items?itemName=mun-lang.mun 15 | 16 | Provides [Mun](https://mun-lang.org) language integration with Visual Studio 17 | Code. 18 | 19 | ## License 20 | 21 | ### VS Code Extension: Polyform Noncommercial 22 | 23 | The Mun Visual Studio Code Extension is licensed under: 24 | 25 | PolyForm Noncommercial License, Version 1.0.0, ([LICENSE.md](LICENSE.md) or https://polyformproject.org/licenses/noncommercial/1.0.0/ 26 | 27 | ### Mun runtime: Apache / MIT 28 | 29 | The Mun runtime is licensed under either of 30 | 31 | * Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0) 32 | * MIT license, http://opensource.org/licenses/MIT) 33 | 34 | at your option. -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mun-lang/vscode-extension/bbe1ebde2879ac4af853ad5f4bf43911c77a3c26/icon.png -------------------------------------------------------------------------------- /language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "//", 4 | "blockComment": [ "/*", "*/" ] 5 | }, 6 | // symbols used as brackets 7 | "brackets": [ 8 | ["{", "}"], 9 | ["[", "]"], 10 | ["(", ")"], 11 | ], 12 | "colorizedBracketPairs": [ 13 | ["{", "}"], 14 | ["[", "]"], 15 | ["(", ")"] 16 | ], 17 | // symbols that are auto closed when typing 18 | "autoClosingPairs": [ 19 | { "open": "{", "close": "}" }, 20 | { "open": "[", "close": "]" }, 21 | { "open": "(", "close": ")" }, 22 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 23 | { "open": "'", "close": "'", "notIn": ["string"] }, 24 | { "open": "/*", "close": " */" } 25 | ], 26 | "autoCloseBefore": ";:.,=}])> \n\t", 27 | // symbols that can be used to surround a selection 28 | "surroundingPairs": [ 29 | ["{", "}"], 30 | ["[", "]"], 31 | ["(", ")"], 32 | ["'", "'"], 33 | ["\"", "\""] 34 | ], 35 | "indentationRules": { 36 | "increaseIndentPattern": "^.*\\{[^}\"']*$|^.*\\([^\\)\"']*$", 37 | "decreaseIndentPattern": "^\\s*(\\s*\\/[*].*[*]\\/\\s*)*[})]" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mun", 3 | "displayName": "Mun", 4 | "version": "0.3.0", 5 | "preview": true, 6 | "icon": "icon.png", 7 | "description": "Mun language integration", 8 | "main": "./dist/main.js", 9 | "publisher": "mun-lang", 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/mun-lang/mun.git" 13 | }, 14 | "author": "The Mun Team ", 15 | "license": "PolyForm-Noncommercial-1.0.0", 16 | "bugs": { 17 | "url": "https://github.com/mun-lang/mun/issues" 18 | }, 19 | "categories": [ 20 | "Programming Languages" 21 | ], 22 | "keywords": [ 23 | "mun" 24 | ], 25 | "homepage": "https://github.com/mun-lang/mun#readme", 26 | "devDependencies": { 27 | "@rollup/plugin-commonjs": "^17.0.0", 28 | "@rollup/plugin-node-resolve": "^13.0.0", 29 | "@types/vscode": "^1.45.1", 30 | "@typescript-eslint/eslint-plugin": "^2.34.0", 31 | "@typescript-eslint/parser": "^2.34.0", 32 | "eslint": "^7.1.0", 33 | "esbuild": "^0.14.27", 34 | "tslib": "^2.3.0", 35 | "typescript": "^4.6.3", 36 | "typescript-formatter": "^7.2.2", 37 | "vsce": "^2.7.0" 38 | }, 39 | "scripts": { 40 | "vscode:prepublish": "npm run build-base -- --minify", 41 | "build-base": "esbuild ./src/main.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --target=node16", 42 | "package": "vsce package", 43 | "build": "npm run build-base -- --sourcemap", 44 | "watch": "npm run build-base -- --sourcemap --watch", 45 | "lint": "tsfmt --verify && eslint -c .eslintrc.js --ext ts ./src", 46 | "fmt": " tsfmt -r && eslint -c .eslintrc.js --ext ts ./src --fix" 47 | }, 48 | "activationEvents": [ 49 | "onLanguage:mun", 50 | "workspaceContains:**/mun.toml" 51 | ], 52 | "engines": { 53 | "vscode": "^1.45.1" 54 | }, 55 | "contributes": { 56 | "languages": [ 57 | { 58 | "id": "mun", 59 | "aliases": [ 60 | "Mun", 61 | "mun" 62 | ], 63 | "extensions": [ 64 | ".mun" 65 | ], 66 | "configuration": "language-configuration.json" 67 | } 68 | ], 69 | "grammars": [ 70 | { 71 | "language": "mun", 72 | "scopeName": "source.mun", 73 | "path": "syntaxes/mun.tmGrammar.json" 74 | } 75 | ], 76 | "configuration": { 77 | "type": "object", 78 | "title": "Mun", 79 | "properties": { 80 | "mun.executablePath": { 81 | "type": [ 82 | "null", 83 | "string" 84 | ], 85 | "default": null, 86 | "description": "Path to the Mun executable" 87 | }, 88 | "mun.trace.server": { 89 | "type": "string", 90 | "scope": "window", 91 | "enum": [ 92 | "off", 93 | "messages", 94 | "verbose" 95 | ], 96 | "enumDescriptions": [ 97 | "No traces", 98 | "Error only", 99 | "Full log" 100 | ], 101 | "default": "off", 102 | "description": "Trace requests to the Mun language server" 103 | } 104 | } 105 | } 106 | }, 107 | "dependencies": { 108 | "vscode-languageclient": "^6.1.3" 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/client.ts: -------------------------------------------------------------------------------- 1 | import * as lc from "vscode-languageclient"; 2 | import * as vscode from "vscode"; 3 | 4 | /** 5 | * Create the configuration for a Mun language client 6 | * @param munExecutablePath The path to the Mun executable 7 | * @param cwd The directory to use as a working directory for the Mun executable. 8 | */ 9 | export function createLanguageClient(munExecutablePath: string, cwd: string): lc.LanguageClient { 10 | const run: lc.Executable = { 11 | command: munExecutablePath, 12 | args: ["language-server"], 13 | options: { 14 | cwd, 15 | }, 16 | } 17 | 18 | const serverOptions: lc.ServerOptions = { 19 | run, 20 | debug: { 21 | ...run, 22 | options: { 23 | ...run.options, 24 | env: { 25 | "RUST_LOG": "mun_language_server=trace" 26 | } 27 | } 28 | } 29 | } 30 | 31 | const traceOutputChannel = vscode.window.createOutputChannel( 32 | "Mun Language Server Trace" 33 | ); 34 | 35 | const clientOptions: lc.LanguageClientOptions = { 36 | documentSelector: [{ scheme: "file", language: "mun" }], 37 | initializationOptions: vscode.workspace.getConfiguration("mun"), 38 | traceOutputChannel, 39 | } 40 | 41 | const client = new lc.LanguageClient( 42 | "mun", 43 | "Mun Language Server", 44 | serverOptions, 45 | clientOptions, 46 | ); 47 | 48 | return client 49 | } 50 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | /** 4 | * The `Config` class is a class that holds and maintain the configuration for the extension. 5 | */ 6 | export class Config { 7 | readonly extensionId = "mun-lang.mun" 8 | readonly rootSection = "mun" 9 | 10 | private readonly requiresReloadOpts = [ 11 | "executablePath", 12 | ] 13 | .map(opt => `${this.rootSection}.${opt}`); 14 | 15 | readonly package: { 16 | version: string; 17 | } = vscode.extensions.getExtension(this.extensionId)!.packageJSON; 18 | 19 | constructor(ctx: vscode.ExtensionContext) { 20 | vscode.workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, ctx.subscriptions); 21 | this.refreshLogging() 22 | } 23 | 24 | /** 25 | * Update what we do with logging based on the current configuration. 26 | */ 27 | private refreshLogging() { 28 | console.info( 29 | "Extension version: ", this.package.version, 30 | "using configuration: ", this.cfg) 31 | } 32 | 33 | /** 34 | * Called when the configuration of the extension changed. 35 | * @param event Information about what transpired 36 | */ 37 | private async onDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) { 38 | this.refreshLogging(); 39 | 40 | const requiresReloadOpt = this.requiresReloadOpts.find( 41 | opt => event.affectsConfiguration(opt) 42 | ); 43 | 44 | if (!requiresReloadOpt) return; 45 | 46 | const userResponse = await vscode.window.showInformationMessage( 47 | `Changing "${requiresReloadOpt}" requires a reload`, 48 | "Reload now" 49 | ); 50 | 51 | if (userResponse === "Reload now") { 52 | await vscode.commands.executeCommand("workbench.action.reloadWindow"); 53 | } 54 | } 55 | 56 | private get cfg(): vscode.WorkspaceConfiguration { 57 | return vscode.workspace.getConfiguration(this.rootSection); 58 | } 59 | private get(path: string): T { 60 | return this.cfg.get(path)!; 61 | } 62 | 63 | get executablePath() { return this.get("executablePath") } 64 | } 65 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import * as os from "os" 2 | 3 | import { ExtensionContext } from "vscode"; 4 | import { Config } from "./config"; 5 | import { createLanguageClient } from "./client"; 6 | import { LanguageClient } from "vscode-languageclient"; 7 | 8 | let client: LanguageClient | null; 9 | 10 | /** 11 | * Called when the plugin is activated 12 | * @param context The vscode context for this extension 13 | */ 14 | export async function activate(context: ExtensionContext) { 15 | 16 | const config = new Config(context); 17 | 18 | // Bootstrap the extension, this returns an optional Mun executable path which we can use to 19 | // initialize a language server with 20 | const executablePath = await bootstrap(config); 21 | if (executablePath != null) { 22 | // TODO: Turn this into a warning when the language server is actually useful 23 | 24 | // Initialize the language client and wait for it to load 25 | client = createLanguageClient(executablePath, ".") 26 | context.subscriptions.push(client.start()); 27 | await client.onReady(); 28 | console.log("started Mun language server") 29 | } 30 | } 31 | 32 | /** 33 | * Called when the plugin is deactivated 34 | */ 35 | export function deactivate() { 36 | // Stop the language client if one was initialized 37 | if (client) { 38 | client.stop(); 39 | client = null 40 | } 41 | } 42 | 43 | /** 44 | * Called to bootstrap the extension before its is started 45 | * @param config The vscode context for this extension 46 | */ 47 | async function bootstrap(config: Config): Promise { 48 | /// Try to get the Mun executable 49 | const path = await getExecutable(config); 50 | if (!path) { 51 | return null 52 | } 53 | 54 | console.log("Using mun binary at", path); 55 | 56 | return path 57 | } 58 | 59 | /** 60 | * Find the Mun executable somewhere. 61 | * @param config The vscode context for this extension 62 | */ 63 | async function getExecutable(config: Config): Promise { 64 | const explicitPath = process.env.__MUN_BIN_DEBUG ?? config.executablePath; 65 | if (explicitPath) { 66 | if (explicitPath.startsWith("~/")) { 67 | return os.homedir() + explicitPath.slice("~".length); 68 | } 69 | return explicitPath; 70 | } 71 | 72 | return null; 73 | } 74 | -------------------------------------------------------------------------------- /syntaxes/mun.tmGrammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "Mun", 4 | "scopeName": "source.mun", 5 | "patterns": [ 6 | { 7 | "include": "#block_doc_comment" 8 | }, 9 | { 10 | "include": "#block_comment" 11 | }, 12 | { 13 | "include": "#line_doc_comment" 14 | }, 15 | { 16 | "include": "#line_comment" 17 | }, 18 | { 19 | "comment": "Floating point literal (fraction)", 20 | "name": "constant.numeric.float.mun", 21 | "match": "\\b[0-9][0-9_]*\\.[0-9][0-9_]*([eE][+-]?[0-9_]+)?(f32|f64)?\\b" 22 | }, 23 | { 24 | "comment": "Floating point literal (exponent)", 25 | "name": "constant.numeric.float.mun", 26 | "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?[eE][+-]?[0-9_]+(f32|f64)?\\b" 27 | }, 28 | { 29 | "comment": "Floating point literal (typed)", 30 | "name": "constant.numeric.float.mun", 31 | "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?([eE][+-]?[0-9_]+)?(f32|f64)\\b" 32 | }, 33 | { 34 | "comment": "Integer literal (decimal)", 35 | "name": "constant.numeric.integer.decimal.mun", 36 | "match": "\\b[0-9][0-9_]*([ui](8|16|32|64|128|s|size))?\\b" 37 | }, 38 | { 39 | "comment": "Integer literal (hexadecimal)", 40 | "name": "constant.numeric.integer.hexadecimal.mun", 41 | "match": "\\b0x[a-fA-F0-9_]+([ui](8|16|32|64|128|s|size))?\\b" 42 | }, 43 | { 44 | "comment": "Integer literal (octal)", 45 | "name": "constant.numeric.integer.octal.mun", 46 | "match": "\\b0o[0-7_]+([ui](8|16|32|64|128|s|size))?\\b" 47 | }, 48 | { 49 | "comment": "Integer literal (binary)", 50 | "name": "constant.numeric.integer.binary.mun", 51 | "match": "\\b0b[01_]+([ui](8|16|32|64|128|s|size))?\\b" 52 | }, 53 | { 54 | "comment": "Boolean constant", 55 | "name": "constant.language.boolean.mun", 56 | "match": "\\b(true|false)\\b" 57 | }, 58 | { 59 | "comment": "Control keyword", 60 | "name": "keyword.control.mun", 61 | "match": "\\b(break|else|if|loop|return|while)\\b" 62 | }, 63 | { 64 | "comment": "Keyword", 65 | "name": "keyword.other.mun", 66 | "match": "\\b(extern|let|use|self|super|package)\\b" 67 | }, 68 | { 69 | "include": "#pub" 70 | }, 71 | { 72 | "comment": "Comparison operator", 73 | "name": "keyword.operator.comparison.mun", 74 | "match": "(&&|\\|\\||==|!=)" 75 | }, 76 | { 77 | "comment": "Assignment operator", 78 | "name": "keyword.operator.assignment.mun", 79 | "match": "(\\+=|-=|/=|\\*=|%=|\\^=|&=|\\|=|<<=|>>=|=)" 80 | }, 81 | { 82 | "comment": "Arithmetic operator", 83 | "name": "keyword.operator.arithmetic.mun", 84 | "match": "(!|\\+|-|/|\\*|%|\\^|&|\\||<<|>>)" 85 | }, 86 | { 87 | "comment": "Comparison operator (second group because of regex precedence)", 88 | "name": "keyword.operator.comparison.mun", 89 | "match": "(<=|>=|<|>)" 90 | }, 91 | { 92 | "include": "#core_types" 93 | }, 94 | { 95 | "comment": "Type declaration", 96 | "begin": "\\b(struct)\\s*(\\([a-z]*\\))?\\s+([a-zA-Z_][a-zA-Z0-9_]*)", 97 | "end": "[\\{\\(;]", 98 | "beginCaptures": { 99 | "1": { 100 | "name": "storage.type.mun" 101 | }, 102 | "2": { 103 | "patterns": [ 104 | { 105 | "include": "#struct_storage" 106 | } 107 | ] 108 | }, 109 | "3": { 110 | "name": "entity.name.type.mun" 111 | } 112 | }, 113 | "patterns": [ 114 | { 115 | "include": "#block_comment" 116 | }, 117 | { 118 | "include": "#line_comment" 119 | }, 120 | { 121 | "include": "#core_types" 122 | }, 123 | { 124 | "include": "#pub" 125 | } 126 | ] 127 | }, 128 | { 129 | "comment": "Type alias", 130 | "begin": "\\b(type)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", 131 | "end": ";", 132 | "beginCaptures": { 133 | "1": { 134 | "name": "storage.type.mun" 135 | }, 136 | "2": { 137 | "name": "entity.name.type.mun" 138 | } 139 | }, 140 | "patterns": [ 141 | { 142 | "include": "#block_comment" 143 | }, 144 | { 145 | "include": "#line_comment" 146 | }, 147 | { 148 | "include": "#core_types" 149 | } 150 | ] 151 | }, 152 | { 153 | "comment": "Function call", 154 | "match": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*\\(", 155 | "captures": { 156 | "1": { 157 | "name": "entity.name.function.mun" 158 | } 159 | } 160 | }, 161 | { 162 | "comment": "Function definition", 163 | "begin": "\\b(fn)\\s+([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)", 164 | "end": "[\\{;]", 165 | "beginCaptures": { 166 | "1": { 167 | "name": "keyword.other.fn.mun" 168 | }, 169 | "2": { 170 | "name": "entity.name.function.mun" 171 | } 172 | }, 173 | "patterns": [ 174 | { 175 | "include": "#block_comment" 176 | }, 177 | { 178 | "include": "#line_comment" 179 | }, 180 | { 181 | "include": "#core_types" 182 | }, 183 | { 184 | "comment": "Function arguments", 185 | "match": "\bfn\b", 186 | "name": "keyword.other.fn.mun" 187 | } 188 | ] 189 | } 190 | ], 191 | "repository": { 192 | "block_doc_comment": { 193 | "comment": "Block documentation comment", 194 | "name": "comment.block.documentation.mun", 195 | "begin": "/\\*[\\*!](?![\\*/])", 196 | "end": "\\*/", 197 | "patterns": [ 198 | { 199 | "include": "#block_doc_comment" 200 | }, 201 | { 202 | "include": "#block_comment" 203 | } 204 | ] 205 | }, 206 | "block_comment": { 207 | "comment": "Block comment", 208 | "name": "comment.block.mun", 209 | "begin": "/\\*", 210 | "end": "\\*/", 211 | "patterns": [ 212 | { 213 | "include": "#block_doc_comment" 214 | }, 215 | { 216 | "include": "#block_comment" 217 | } 218 | ] 219 | }, 220 | "line_doc_comment": { 221 | "comment": "Single-line documentation comment", 222 | "name": "comment.line.documentation.mun", 223 | "begin": "//[!/](?=[^/])", 224 | "end": "$" 225 | }, 226 | "line_comment": { 227 | "comment": "Single-line comment", 228 | "name": "comment.line.double-slash.mun", 229 | "begin": "//", 230 | "end": "$" 231 | }, 232 | "core_types": { 233 | "comment": "Built-in/core type", 234 | "name": "storage.type.primitive.mun", 235 | "match": "\\b(bool|usize|isize|u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|f32|f64)\\b" 236 | }, 237 | "pub": { 238 | "comment": "Visibility modifier", 239 | "name": "storage.modifier.visibility.mun", 240 | "match": "\\bpub\\b" 241 | }, 242 | "type": { 243 | "comment": "A type", 244 | "name": "entity.name.type.mun", 245 | "match": "\\b([A-Za-z][_A-Za-z0-9]*|_[_A-Za-z0-9]+)\\b" 246 | }, 247 | "struct_storage": { 248 | "comment": "Struct storage specifier", 249 | "name": "storage.modifier.struct.mun", 250 | "match": "\\b(gc|value)\\b" 251 | } 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2021", 5 | "outDir": "dist", 6 | "lib": [ 7 | "es2021" 8 | ], 9 | "esModuleInterop": true, 10 | "allowSyntheticDefaultImports": true, 11 | "sourceMap": true, 12 | "rootDir": "src", 13 | "strict": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "newLine": "LF", 19 | "importHelpers": true 20 | }, 21 | "exclude": [ 22 | "node_modules" 23 | ] 24 | } 25 | --------------------------------------------------------------------------------