├── snippets
└── sway.json
├── .prettierignore
├── images
├── logo.png
├── dark
│ ├── sway.png
│ ├── play.svg
│ ├── edit.svg
│ └── refresh.svg
├── light
│ ├── sway.png
│ ├── play.svg
│ ├── edit.svg
│ └── refresh.svg
└── fuel.svg
├── .gitattributes
├── client
├── test
│ └── syntaxes
│ │ ├── basic_predicate.sw
│ │ ├── const_decl.sw
│ │ ├── storage_declaration.sw
│ │ ├── smo_opcode.sw
│ │ ├── match_expressions_mismatched.sw
│ │ ├── chained_if_let.sw
│ │ ├── particle.sw
│ │ ├── basic_predicate.sw.snap
│ │ ├── const_decl.sw.snap
│ │ ├── storage_declaration.sw.snap
│ │ ├── smo_opcode.sw.snap
│ │ ├── match_expressions_mismatched.sw.snap
│ │ ├── chained_if_let.sw.snap
│ │ └── particle.sw.snap
├── src
│ ├── commands
│ │ ├── forcBuild.ts
│ │ ├── forcRun.ts
│ │ ├── installServer.ts
│ │ ├── startFuelCore.ts
│ │ ├── forcTest.ts
│ │ ├── goToLocation.ts
│ │ ├── stopFuelCore.ts
│ │ ├── peekLocations.ts
│ │ ├── openAstFile.ts
│ │ └── openDotGraph.ts
│ ├── client.ts
│ ├── interface
│ │ ├── visualize.ts
│ │ ├── showAst.ts
│ │ └── onEnter.ts
│ ├── util
│ │ ├── convert.ts
│ │ └── util.ts
│ ├── status_bar
│ │ └── fuelCoreStatus.ts
│ ├── config.ts
│ ├── palettes.ts
│ ├── program.ts
│ └── main.ts
└── tsconfig.json
├── .vscodeignore
├── .prettierrc.json
├── scripts
└── e2e.sh
├── tsconfig.json
├── .github
└── workflows
│ ├── conventional-commits.yml
│ ├── marketplace-publish.yml
│ ├── changelog.yml
│ └── ci.yml
├── .vscode
├── tasks.json
└── launch.json
├── language-configuration.json
├── README.md
├── docs
└── testing.md
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── package.json
└── syntaxes
└── sway.tmLanguage.json
/snippets/sway.json:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # Ignore artifacts:
2 | build
3 | coverage
4 |
--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FuelLabs/sway-vscode-plugin/HEAD/images/logo.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behavior to automatically normalize line endings.
2 | * text=auto
3 |
4 |
--------------------------------------------------------------------------------
/client/test/syntaxes/basic_predicate.sw:
--------------------------------------------------------------------------------
1 | predicate;
2 |
3 | fn main() -> bool {
4 | true
5 | }
6 |
--------------------------------------------------------------------------------
/images/dark/sway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FuelLabs/sway-vscode-plugin/HEAD/images/dark/sway.png
--------------------------------------------------------------------------------
/images/light/sway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FuelLabs/sway-vscode-plugin/HEAD/images/light/sway.png
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | .gitignore
4 | vsc-extension-quickstart.md
5 | node_modules
6 | **/*.ts
7 | **/tsconfig.json
8 |
--------------------------------------------------------------------------------
/client/test/syntaxes/const_decl.sw:
--------------------------------------------------------------------------------
1 | script;
2 |
3 | const GLOBAL_VAL: u64 = 99;
4 |
5 | fn main() -> u64 {
6 | const LOCAL_VAL = 1;
7 | GLOBAL_VAL + LOCAL_VAL
8 | }
9 |
--------------------------------------------------------------------------------
/client/test/syntaxes/storage_declaration.sw:
--------------------------------------------------------------------------------
1 | contract;
2 | storage {
3 | supply: u64 = 0,
4 | demand: u64 = 0,
5 | name: str[4] = "test",
6 | }
7 | fn main() {
8 | }
9 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "semi": true,
4 | "singleQuote": true,
5 | "bracketSpacing": true,
6 | "trailingComma": "es5",
7 | "arrowParens": "avoid"
8 | }
--------------------------------------------------------------------------------
/scripts/e2e.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export CODE_TESTS_PATH="$(pwd)/client/out/test"
4 | export CODE_TESTS_WORKSPACE="$(pwd)/client/testFixture"
5 |
6 | node "$(pwd)/client/out/test/runTest"
--------------------------------------------------------------------------------
/client/src/commands/forcBuild.ts:
--------------------------------------------------------------------------------
1 | import { Terminal } from '../util/util';
2 |
3 | export default function forcBuild(forcDir: string) {
4 | Terminal.Sway.execute(`cd ${forcDir} && forc build`);
5 | }
6 |
--------------------------------------------------------------------------------
/client/src/commands/forcRun.ts:
--------------------------------------------------------------------------------
1 | import { Terminal } from '../util/util';
2 |
3 | export default function forcRun(forcDir: string) {
4 | Terminal.Sway.execute(`cd ${forcDir} && forc run --unsigned`);
5 | }
6 |
--------------------------------------------------------------------------------
/client/src/commands/installServer.ts:
--------------------------------------------------------------------------------
1 | import { Terminal } from '../util/util';
2 |
3 | export default function installServer() {
4 | Terminal.Sway.execute(
5 | `curl --proto '=https' --tlsv1.2 -sSf https://install.fuel.network/fuelup-init.sh | sh`
6 | );
7 | }
8 |
--------------------------------------------------------------------------------
/client/test/syntaxes/smo_opcode.sw:
--------------------------------------------------------------------------------
1 | script;
2 |
3 | use std::constants::ZERO_B256;
4 |
5 | fn main() -> bool {
6 | asm(recipient: ZERO_B256, msg_len: 0, output: 0, coins: 0) {
7 | smo recipient msg_len coins output;
8 | }
9 | true
10 | }
11 |
--------------------------------------------------------------------------------
/client/src/commands/startFuelCore.ts:
--------------------------------------------------------------------------------
1 | import { window } from 'vscode';
2 | import { Terminal } from '../util/util';
3 |
4 | export default function startFuelCore() {
5 | Terminal.FuelCore.execute(`fuel-core run --db-type in-memory`);
6 | window.showInformationMessage(`Started fuel-core`);
7 | }
8 |
--------------------------------------------------------------------------------
/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es2019",
5 | "lib": ["ES2019"],
6 | "outDir": "out",
7 | "rootDir": "src",
8 | "sourceMap": true
9 | },
10 | "include": ["src"],
11 | "exclude": ["node_modules", ".vscode-test"]
12 | }
13 |
--------------------------------------------------------------------------------
/client/src/commands/forcTest.ts:
--------------------------------------------------------------------------------
1 | import { Terminal } from '../util/util';
2 |
3 | export default function forcTest(forcDir: string, _testName?: string) {
4 | // TODO: add support for running specific tests when
5 | // https://github.com/FuelLabs/sway/issues/3268 is resolved
6 | Terminal.Sway.execute(`cd ${forcDir} && forc test`);
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es2019",
5 | "lib": ["ES2019"],
6 | "outDir": "out",
7 | "rootDir": "src",
8 | "sourceMap": true
9 | },
10 | "include": ["src"],
11 | "exclude": ["node_modules", ".vscode-test"],
12 | "references": [{ "path": "./client" }]
13 | }
14 |
--------------------------------------------------------------------------------
/client/src/commands/goToLocation.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as lc from 'vscode-languageclient';
3 | import { toVSCodeRange, toVSCodeUri } from '../util/convert';
4 |
5 | export default async function goToLocation({ uri, range }: lc.Location) {
6 | await vscode.window.showTextDocument(toVSCodeUri(uri), {
7 | selection: toVSCodeRange(range),
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/images/light/play.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/dark/play.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/client/src/commands/stopFuelCore.ts:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 | import { window } from 'vscode';
3 | import updateFuelCoreStatus from '../status_bar/fuelCoreStatus';
4 |
5 | export default function stopFuelCore() {
6 | // Using exec instead of the Terminal utility here because we don't need the user to see the
7 | // command output.
8 | exec(`pkill -15 fuel-core`, () => {
9 | window.showInformationMessage(`Stopped fuel-core`);
10 | updateFuelCoreStatus();
11 | });
12 | }
13 |
--------------------------------------------------------------------------------
/client/test/syntaxes/match_expressions_mismatched.sw:
--------------------------------------------------------------------------------
1 | script;
2 |
3 | struct MyStruct {
4 | a: u64,
5 | b: u64,
6 | }
7 |
8 | enum MyEnum {
9 | Variant1: (),
10 | Variant2: u64,
11 | Variant3: MyStruct,
12 | }
13 |
14 | fn main() -> u64 {
15 | let x = MyEnum::Variant1;
16 | let y = MyEnum::Variant2(5);
17 | let z = MyEnum::Variant3(MyStruct {
18 | a: 0, b: 1
19 | });
20 |
21 | match y {
22 | MyEnum::Variant2(y) => y, _ => 10,
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/client/test/syntaxes/chained_if_let.sw:
--------------------------------------------------------------------------------
1 | script;
2 |
3 | enum Result {
4 | Ok: T,
5 | Err: E,
6 | }
7 |
8 | // should return 5
9 | fn main() -> u64 {
10 | let result_a = Result::Ok::(5u64);
11 | let result_b = Result::Err::(false);
12 |
13 | if let Result::Err(a) = result_a {
14 | 6
15 | } else if let Result::Ok(num) = result_b {
16 | 10
17 | } else if let Result::Ok(num) = result_a {
18 | num
19 | } else {
20 | 42
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/images/dark/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/light/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/workflows/conventional-commits.yml:
--------------------------------------------------------------------------------
1 | name: PR Conventional Commit Validation
2 |
3 | on:
4 | pull_request:
5 | types: [opened, synchronize, reopened, edited]
6 |
7 | jobs:
8 | validate-pr-title:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | pull-requests: read
12 | steps:
13 | - name: PR Conventional Commit Validation
14 | uses: ytanikin/PRConventionalCommits@1.1.0
15 | with:
16 | task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
17 | token: ${{ secrets.GITHUB_TOKEN }}
18 | add_label: 'false'
19 |
--------------------------------------------------------------------------------
/.github/workflows/marketplace-publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish Extension
2 |
3 | on:
4 | release:
5 | types: [created]
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | environment: vscode-deploy
11 | steps:
12 | - uses: actions/checkout@v2
13 |
14 | - uses: actions/setup-node@v1
15 | with:
16 | node-version: 16
17 |
18 | - run: npm ci
19 |
20 | - name: Publish to Visual Studio Marketplace
21 | uses: HaaLeo/publish-vscode-extension@v1
22 | with:
23 | pat: ${{ secrets.VS_MARKETPLACE_TOKEN }}
24 | registryUrl: https://marketplace.visualstudio.com
25 |
--------------------------------------------------------------------------------
/client/src/commands/peekLocations.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as lc from 'vscode-languageclient';
3 | import { toVSCodeLocation } from '../util/convert';
4 |
5 | export interface PeekLocationsParams {
6 | locations: lc.Location[];
7 | }
8 |
9 | export default async function peekLocations({
10 | locations,
11 | }: PeekLocationsParams) {
12 | const uri = vscode.window.activeTextEditor.document.uri;
13 | const position = vscode.window.activeTextEditor.selection.active;
14 | vscode.commands.executeCommand(
15 | 'editor.action.peekLocations',
16 | uri,
17 | position,
18 | locations.map(toVSCodeLocation),
19 | 'peek'
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "type": "npm",
6 | "script": "compile",
7 | "group": "build",
8 | "presentation": {
9 | "panel": "dedicated",
10 | "reveal": "never"
11 | },
12 | "problemMatcher": ["$tsc"]
13 | },
14 | {
15 | "type": "npm",
16 | "script": "watch",
17 | "isBackground": true,
18 | "group": {
19 | "kind": "build",
20 | "isDefault": true
21 | },
22 | "presentation": {
23 | "panel": "dedicated",
24 | "reveal": "never"
25 | },
26 | "problemMatcher": ["$esbuild-watch"]
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/.github/workflows/changelog.yml:
--------------------------------------------------------------------------------
1 | name: Update Changelog
2 | on:
3 | # Manually triggered
4 | workflow_dispatch:
5 |
6 | jobs:
7 | update-changelog:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | with:
12 | fetch-depth: 0
13 | - name: Generate changelog and push
14 | uses: BobAnkh/auto-generate-changelog@v1.2.5
15 | with:
16 | ACCESS_TOKEN: ${{secrets.REPO_TOKEN}}
17 | COMMIT_MESSAGE: 'docs(CHANGELOG): Update release notes'
18 | PATH: 'CHANGELOG.md'
19 | TYPE: 'feat:Feature,fix:Bug Fixes,docs:Documentation,refactor:Refactor,perf:Performance Improvements,chore:Chores'
20 |
--------------------------------------------------------------------------------
/client/src/client.ts:
--------------------------------------------------------------------------------
1 | import {
2 | LanguageClient,
3 | LanguageClientOptions,
4 | ServerOptions,
5 | } from 'vscode-languageclient/node';
6 | import { EXTENSION_ROOT } from './config';
7 |
8 | let client: LanguageClient | null;
9 |
10 | export const createClient = (
11 | clientOptions: LanguageClientOptions,
12 | serverOptions: ServerOptions
13 | ): LanguageClient => {
14 | if (client) {
15 | throw new Error('Client already exists!');
16 | }
17 | client = new LanguageClient(
18 | EXTENSION_ROOT,
19 | 'Sway Language Server',
20 | serverOptions,
21 | clientOptions
22 | );
23 | return client;
24 | };
25 |
26 | export const getClient = (): LanguageClient => client;
27 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "type": "lldb",
6 | "request": "attach",
7 | "name": "Sway Server",
8 | "program": "forc",
9 | "args": ["lsp"]
10 | },
11 | {
12 | "type": "extensionHost",
13 | "request": "launch",
14 | "name": "Launch Client",
15 | "runtimeExecutable": "${execPath}",
16 | "args": ["--extensionDevelopmentPath=${workspaceRoot}"],
17 | "outFiles": ["${workspaceRoot}/client/out/**/*.js"],
18 | "preLaunchTask": {
19 | "type": "npm",
20 | "script": "esbuild"
21 | }
22 | }
23 | ],
24 | "compounds": [
25 | {
26 | "name": "Client + Server",
27 | "configurations": ["Launch Client", "Sway Server"]
28 | }
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/client/src/interface/visualize.ts:
--------------------------------------------------------------------------------
1 | import {
2 | RequestType,
3 | TextDocumentIdentifier,
4 | } from 'vscode-languageclient/node';
5 | import { getClient } from '../client';
6 |
7 | export type GraphKind = 'build_plan';
8 |
9 | interface VisualizeParams {
10 | textDocument: TextDocumentIdentifier;
11 | graphKind: GraphKind;
12 | }
13 |
14 | const request = new RequestType(
15 | 'sway/visualize'
16 | );
17 |
18 | export const visualize = async (
19 | filePath: string,
20 | graphKind: GraphKind
21 | ): Promise => {
22 | const client = getClient();
23 | const params: VisualizeParams = {
24 | textDocument: {
25 | uri: filePath,
26 | },
27 | graphKind,
28 | };
29 | return await client.sendRequest(request, params);
30 | };
31 |
--------------------------------------------------------------------------------
/client/test/syntaxes/particle.sw:
--------------------------------------------------------------------------------
1 | script;
2 |
3 | /// A simple Particle struct
4 | pub struct Particle {
5 | position: [u64; 3],
6 | velocity: [u64; 3],
7 | acceleration: [u64; 3],
8 | mass: u64,
9 | }
10 |
11 | impl Particle {
12 | /// Creates a new Particle with the given position, velocity, acceleration, and mass
13 | fn new(position: [u64; 3], velocity: [u64; 3], acceleration: [u64; 3], mass: u64) -> Particle {
14 | Particle {
15 | position: position,
16 | velocity: velocity,
17 | acceleration: acceleration,
18 | mass: mass,
19 | }
20 | }
21 | }
22 |
23 | fn main() {
24 | let position = [0, 0, 0];
25 | let velocity = [0, 1, 0];
26 | let acceleration = [1, 1, position[1]];
27 | let mass = 10;
28 | let p = ~Particle::new(position, velocity, acceleration, mass);
29 | }
30 |
--------------------------------------------------------------------------------
/language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | // symbol used for single line comment. Remove this entry if your language does not support line comments
4 | "lineComment": "//",
5 | // symbols used for start and end a block comment. Remove this entry if your language does not support block comments
6 | "blockComment": ["/*", "*/"]
7 | },
8 | // symbols used as brackets
9 | "brackets": [
10 | ["{", "}"],
11 | ["[", "]"],
12 | ["(", ")"]
13 | ],
14 | // symbols that are auto closed when typing
15 | "autoClosingPairs": [
16 | ["{", "}"],
17 | ["[", "]"],
18 | ["(", ")"],
19 | ["\"", "\""],
20 | ["'", "'"]
21 | ],
22 | // symbols that can be used to surround a selection
23 | "surroundingPairs": [
24 | ["{", "}"],
25 | ["[", "]"],
26 | ["(", ")"],
27 | ["\"", "\""],
28 | ["'", "'"]
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/client/src/interface/showAst.ts:
--------------------------------------------------------------------------------
1 | import {
2 | DocumentUri,
3 | RequestType,
4 | TextDocumentIdentifier,
5 | } from 'vscode-languageclient/node';
6 | import { getClient } from '../client';
7 |
8 | export type AstKind = 'lexed' | 'parsed' | 'typed';
9 |
10 | interface ShowAstParams {
11 | textDocument: TextDocumentIdentifier;
12 | astKind: AstKind;
13 | savePath: DocumentUri;
14 | }
15 |
16 | const request = new RequestType<
17 | ShowAstParams,
18 | TextDocumentIdentifier | null,
19 | void
20 | >('sway/show_ast');
21 |
22 | export const showAst = async (
23 | filePath: string,
24 | astKind: AstKind,
25 | savePath: string
26 | ): Promise => {
27 | const client = getClient();
28 | const params: ShowAstParams = {
29 | textDocument: {
30 | uri: filePath,
31 | },
32 | astKind,
33 | savePath,
34 | };
35 | return await client.sendRequest(request, params);
36 | };
37 |
--------------------------------------------------------------------------------
/client/src/commands/openAstFile.ts:
--------------------------------------------------------------------------------
1 | import { commands, Uri } from 'vscode';
2 | import { AstKind, showAst } from '../interface/showAst';
3 | import { addFilePrefix, log } from '../util/util';
4 |
5 | const SAVE_PATH = '/tmp/';
6 |
7 | export default async function openAstFile(filePath: string, astKind: AstKind) {
8 | try {
9 | const astDocument = await showAst(
10 | addFilePrefix(filePath),
11 | astKind,
12 | addFilePrefix(SAVE_PATH)
13 | );
14 | if (astDocument) {
15 | const openPath = Uri.parse(astDocument.uri);
16 | await commands.executeCommand('vscode.openFolder', openPath, {
17 | forceNewWindow: true,
18 | });
19 | log.info(`Successfully opened ${astKind} AST file ${filePath}`);
20 | } else {
21 | log.error(`No ${astKind} AST file found for ${filePath}`);
22 | }
23 | } catch (error) {
24 | log.error(`Failed to open ${astKind} AST file for ${filePath}`, error);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/images/dark/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/light/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches: [master]
7 |
8 | jobs:
9 | format:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 | - uses: actions/setup-node@v1
14 | with:
15 | node-version: 16
16 | - run: npm ci
17 | - run: npm run format:check
18 |
19 | build:
20 | needs: [format]
21 | runs-on: ubuntu-latest
22 | steps:
23 | - uses: actions/checkout@v2
24 | - uses: actions/setup-node@v1
25 | with:
26 | node-version: 16
27 |
28 | - run: npm ci
29 | - name: Dry run publish
30 | uses: HaaLeo/publish-vscode-extension@v1
31 | with:
32 | pat: 'quickbrownfox'
33 | dryRun: true
34 | syntaxes:
35 | runs-on: ubuntu-latest
36 |
37 | steps:
38 | - uses: actions/checkout@v2
39 | - uses: actions/setup-node@v1
40 | with:
41 | node-version: 16
42 | - run: npm ci
43 | - run: npm run test-syntaxes
44 |
--------------------------------------------------------------------------------
/client/test/syntaxes/basic_predicate.sw.snap:
--------------------------------------------------------------------------------
1 | >predicate;
2 | #^^^^^^^^^ source.sway source.sway meta.attribute.sway
3 | # ^ source.sway
4 | >
5 | >fn main() -> bool {
6 | #^^ source.sway meta.function.definition.sway keyword.other.fn.sway
7 | # ^ source.sway meta.function.definition.sway
8 | # ^^^^ source.sway meta.function.definition.sway entity.name.function.sway
9 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
10 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
11 | # ^ source.sway meta.function.definition.sway
12 | # ^^ source.sway meta.function.definition.sway keyword.operator.arrow.skinny.sway
13 | # ^ source.sway meta.function.definition.sway
14 | # ^^^^ source.sway meta.function.definition.sway entity.name.type.primitive.sway
15 | # ^ source.sway meta.function.definition.sway
16 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
17 | > true
18 | #^^^^ source.sway
19 | # ^^^^ source.sway constant.language.bool.sway
20 | >}
21 | #^ source.sway punctuation.brackets.curly.sway
22 | >
--------------------------------------------------------------------------------
/client/src/util/convert.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as lc from 'vscode-languageclient';
3 |
4 | export function toVSCodePosition(position: lc.Position): vscode.Position {
5 | return new vscode.Position(position.line, position.character);
6 | }
7 |
8 | export function toVSCodeRange(range: lc.Range): vscode.Range {
9 | return new vscode.Range(
10 | toVSCodePosition(range.start),
11 | toVSCodePosition(range.end)
12 | );
13 | }
14 |
15 | export function toVSCodeUri(uri: lc.DocumentUri): vscode.Uri {
16 | return vscode.Uri.parse(uri);
17 | }
18 |
19 | export function toVSCodeLocation(location: lc.Location): vscode.Location {
20 | return new vscode.Location(
21 | toVSCodeUri(location.uri),
22 | toVSCodeRange(location.range)
23 | );
24 | }
25 |
26 | export function toLSPPosition(position: vscode.Position): lc.Position {
27 | return lc.Position.create(position.line, position.character);
28 | }
29 |
30 | export function toLSPRange(range: vscode.Range): lc.Range {
31 | return lc.Range.create(toLSPPosition(range.start), toLSPPosition(range.end));
32 | }
33 |
34 | export function toLSPUri(uri: vscode.Uri): lc.DocumentUri {
35 | return uri.toString();
36 | }
37 |
38 | export function toLSPLocation(location: vscode.Location): lc.Location {
39 | return lc.Location.create(toLSPUri(location.uri), toLSPRange(location.range));
40 | }
41 |
--------------------------------------------------------------------------------
/client/src/status_bar/fuelCoreStatus.ts:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 | import { StatusBarAlignment, StatusBarItem, ThemeColor, window } from 'vscode';
3 |
4 | let fuelCoreStatus: StatusBarItem;
5 | let isFuelCoreRunning: boolean;
6 |
7 | export const getFuelCoreStatus = () => {
8 | if (!fuelCoreStatus) {
9 | fuelCoreStatus = window.createStatusBarItem(StatusBarAlignment.Left, 100);
10 | }
11 | return fuelCoreStatus;
12 | };
13 |
14 | export default function updateFuelCoreStatus() {
15 | const initializedItem = getFuelCoreStatus();
16 | exec(`ps aux | grep -i fuel-cor`, (_error, stdout, _stderr) => {
17 | isFuelCoreRunning = stdout.includes('fuel-core');
18 | });
19 |
20 | if (isFuelCoreRunning) {
21 | initializedItem.text = '$(symbol-event) running';
22 | initializedItem.command = 'sway.stopFuelCore';
23 | initializedItem.tooltip = 'Stop the locally running fuel-core server';
24 | // Using any string other than the approved theme colors will reset the background to default.
25 | initializedItem.backgroundColor = new ThemeColor('reset');
26 | initializedItem.show();
27 | } else {
28 | initializedItem.text = '$(symbol-event) stopped';
29 | initializedItem.command = 'sway.startFuelCore';
30 | initializedItem.tooltip = 'Start fuel-core server at 127.0.0.1:4000';
31 | initializedItem.backgroundColor = new ThemeColor(
32 | 'statusBarItem.warningBackground'
33 | );
34 | initializedItem.show();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | [](https://marketplace.visualstudio.com/items?itemName=FuelLabs.sway-vscode-plugin)
8 | [](https://discord.gg/xfpK4Pe)
9 |
10 | This extension provides LSP support for the Sway smart contract programming language.
11 |
12 | ## Features
13 |
14 | - goto type definition
15 | - find all references
16 | - types and documentation on hover
17 | - inlay hints for types and parameter names
18 | - semantic syntax highlighting
19 | - symbol renaming
20 | - code actions
21 | - imports insertion
22 |
23 | _Coming Soon_
24 |
25 | - code completion
26 | - apply suggestions from errors
27 | - workspace symbol search
28 | - ... and many more
29 |
30 |
31 | ## Quick start
32 |
33 | 1. Install the [Fuel toolchain](https://fuellabs.github.io/fuelup/master/installation/index.html).
34 | 1. Ensure `forc-lsp` is installed correctly by entering `forc-lsp --version` into your terminal.
35 | 1. Install the [Sway VSCode plugin](https://marketplace.visualstudio.com/items?itemName=FuelLabs.sway-vscode-plugin).
36 |
37 | ## Configuration
38 |
39 | This extension provides configurations through VSCode's configuration settings. All configurations are under `sway-lsp.*`.
40 |
--------------------------------------------------------------------------------
/client/src/interface/onEnter.ts:
--------------------------------------------------------------------------------
1 | import { TextDocumentChangeEvent, window } from 'vscode';
2 | import {
3 | RequestType,
4 | TextDocumentContentChangeEvent,
5 | TextDocumentEdit,
6 | TextDocumentIdentifier,
7 | WorkspaceEdit,
8 | } from 'vscode-languageclient/node';
9 | import { getClient } from '../client';
10 | import { toVSCodeRange } from '../util/convert';
11 | import { addFilePrefix } from '../util/util';
12 |
13 | interface OnEnterParams {
14 | textDocument: TextDocumentIdentifier;
15 | contentChanges: TextDocumentContentChangeEvent[];
16 | }
17 |
18 | const request = new RequestType(
19 | 'sway/on_enter'
20 | );
21 |
22 | export const onEnter = async (changeEvent: TextDocumentChangeEvent) => {
23 | if (
24 | changeEvent.document.uri.scheme === 'file' &&
25 | changeEvent.document.languageId === 'sway' &&
26 | changeEvent.contentChanges.length === 1 &&
27 | changeEvent.contentChanges[0].text.includes('\n')
28 | ) {
29 | const client = getClient();
30 | const params: OnEnterParams = {
31 | textDocument: {
32 | uri: addFilePrefix(changeEvent.document.uri.fsPath),
33 | },
34 | contentChanges: [...changeEvent.contentChanges],
35 | };
36 | const response = await client.sendRequest(request, params);
37 | if (!!response) {
38 | window.activeTextEditor.edit(editBuilder => {
39 | response.documentChanges?.forEach((change: TextDocumentEdit) => {
40 | change.edits.forEach(edit => {
41 | editBuilder.replace(toVSCodeRange(edit.range), edit.newText);
42 | });
43 | });
44 | });
45 | }
46 | }
47 | };
48 |
--------------------------------------------------------------------------------
/docs/testing.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | Prior to testing make sure you have [the Fuel toolchain](https://fuellabs.github.io/sway/latest/introduction/installation.html) installed as well.
4 |
5 | On macOS, ensure you have the `code` CLI tool installed by running `code --version`. If not, open the VSCode editor -> cmd + shift + p -> search `>Shell Command install` -> install. Additional information: .
6 |
7 | ## Testing as a real installed extension
8 |
9 | ```sh
10 | git clone git@github.com:FuelLabs/sway-vscode-plugin.git
11 | cd sway-vscode-plugin
12 | npm i
13 | npm run install-extension
14 | ```
15 |
16 | ## Test your changes on your local install of VS Code
17 |
18 | Firstly, uninstall the official release of the extension and reload VS Code if you have it installed. You will need to do this step each time you want to re-install and test your local version.
19 |
20 | ```sh
21 | cd sway-vscode-plugin
22 | npm i
23 | git checkout
24 | npm run install-extension
25 | ```
26 |
27 | ## Testing in Debug mode
28 |
29 | - In order to start the Debug mode, open `vscode-plugin` in Visual Studio Code, make sure that it is opened as root/main workspace - in order to avoid any problems.
30 | - Make sure that in `Run and Debug` Tab that "Launch Client" is selected - press F5 and new Visual Studio Code Debug Window will be opened.
31 | - Within that Window open a `.sw` file like `main.sw` - which will activate `forc lsp`.
32 |
33 | ## Testing in Debug mode with the attached Server _(This is only needed if you are developing the Server.)_
34 |
35 | - Install this extension -> [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)
36 | - Repeat the steps outlined in "Testing in Debug mode", then go back `Run and Debug` Tab, from the dropdown menu choose "Sway Server" which will attach the server in the debug mode as well.
37 |
38 | ## When does the plugin get activated?
39 |
40 | Currently it gets activated once you open a file with `.sw` extension.
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # Ignore Typescript files
107 | out
108 | .vscode-test
109 | sway-vscode-plugin.vsix
110 |
111 | # .vsix
112 | *.vsix
113 |
--------------------------------------------------------------------------------
/client/src/util/util.ts:
--------------------------------------------------------------------------------
1 | import { inspect } from 'util';
2 | import * as vscode from 'vscode';
3 |
4 | export const addFilePrefix = (path: string) => `file://${path}`;
5 |
6 | export const log = new (class {
7 | private enabled = true;
8 | private readonly output =
9 | vscode.window.createOutputChannel('Sway LSP Client');
10 |
11 | setEnabled(yes: boolean): void {
12 | log.enabled = yes;
13 | }
14 |
15 | // Hint: the type [T, ...T[]] means a non-empty array
16 | debug(...msg: [unknown, ...unknown[]]): void {
17 | if (!log.enabled) return;
18 | log.write('DEBUG', ...msg);
19 | }
20 |
21 | info(...msg: [unknown, ...unknown[]]): void {
22 | log.write('INFO', ...msg);
23 | }
24 |
25 | warn(...msg: [unknown, ...unknown[]]): void {
26 | log.write('WARN', ...msg);
27 | }
28 |
29 | error(...msg: [unknown, ...unknown[]]): void {
30 | log.write('ERROR', ...msg);
31 | log.output.show(true);
32 | }
33 |
34 | private write(label: string, ...messageParts: unknown[]): void {
35 | const message = messageParts.map(log.stringify).join(' ');
36 | const dateTime = new Date().toLocaleString();
37 | log.output.appendLine(`${label} [${dateTime}]: ${message}`);
38 | }
39 |
40 | private stringify(val: unknown): string {
41 | if (typeof val === 'string') return val;
42 | return inspect(val, {
43 | colors: false,
44 | depth: 6, // heuristic
45 | });
46 | }
47 | })();
48 |
49 | // Utilities for interacting with VSCode terminals.
50 | export namespace Terminal {
51 | type Names = 'sway' | 'fuel-core';
52 | class NamedTerminal {
53 | static type: Names;
54 | static execute(cmd: string): void {
55 | const terminal = this.get();
56 | terminal.sendText(cmd);
57 | terminal.show(true);
58 | }
59 |
60 | private static get(): vscode.Terminal {
61 | const existing = vscode.window.terminals.find(t => t.name === this.type);
62 | return existing ?? vscode.window.createTerminal(this.type);
63 | }
64 | }
65 | // Used to execute any commands that are not long-running.
66 | export class Sway extends NamedTerminal {
67 | static type: Names = 'sway';
68 | }
69 | // Only used for starting fuel-core, which is a long-running process.
70 | export class FuelCore extends NamedTerminal {
71 | static type: Names = 'fuel-core';
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/client/test/syntaxes/const_decl.sw.snap:
--------------------------------------------------------------------------------
1 | >script;
2 | #^^^^^^ source.sway source.sway meta.attribute.sway
3 | # ^ source.sway
4 | >
5 | >const GLOBAL_VAL: u64 = 99;
6 | #^^^^^ source.sway storage.type.sway
7 | # ^ source.sway
8 | # ^^^^^^^^^^ source.sway constant.other.caps.sway
9 | # ^ source.sway keyword.operator.key-value.sway
10 | # ^ source.sway
11 | # ^^^ source.sway entity.name.type.numeric.sway
12 | # ^ source.sway
13 | # ^ source.sway keyword.operator.assignment.equal.sway
14 | # ^ source.sway
15 | # ^^ source.sway constant.numeric.decimal.sway
16 | # ^ source.sway punctuation.semi.sway
17 | >
18 | >fn main() -> u64 {
19 | #^^ source.sway meta.function.definition.sway keyword.other.fn.sway
20 | # ^ source.sway meta.function.definition.sway
21 | # ^^^^ source.sway meta.function.definition.sway entity.name.function.sway
22 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
23 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
24 | # ^ source.sway meta.function.definition.sway
25 | # ^^ source.sway meta.function.definition.sway keyword.operator.arrow.skinny.sway
26 | # ^ source.sway meta.function.definition.sway
27 | # ^^^ source.sway meta.function.definition.sway entity.name.type.numeric.sway
28 | # ^ source.sway meta.function.definition.sway
29 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
30 | > const LOCAL_VAL = 1;
31 | #^^^^ source.sway
32 | # ^^^^^ source.sway storage.type.sway
33 | # ^ source.sway
34 | # ^^^^^^^^^ source.sway constant.other.caps.sway
35 | # ^ source.sway
36 | # ^ source.sway keyword.operator.assignment.equal.sway
37 | # ^ source.sway
38 | # ^ source.sway constant.numeric.decimal.sway
39 | # ^ source.sway punctuation.semi.sway
40 | > GLOBAL_VAL + LOCAL_VAL
41 | #^^^^ source.sway
42 | # ^^^^^^^^^^ source.sway constant.other.caps.sway
43 | # ^ source.sway
44 | # ^ source.sway keyword.operator.math.sway
45 | # ^ source.sway
46 | # ^^^^^^^^^ source.sway constant.other.caps.sway
47 | >}
48 | #^ source.sway punctuation.brackets.curly.sway
49 | >
--------------------------------------------------------------------------------
/images/fuel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/test/syntaxes/storage_declaration.sw.snap:
--------------------------------------------------------------------------------
1 | >contract;
2 | #^^^^^^^^ source.sway source.sway meta.attribute.sway
3 | # ^ source.sway
4 | >storage {
5 | #^^^^^^^ source.sway variable.other.sway
6 | # ^ source.sway
7 | # ^ source.sway punctuation.brackets.curly.sway
8 | > supply: u64 = 0,
9 | #^^^^ source.sway
10 | # ^^^^^^ source.sway variable.other.sway
11 | # ^ source.sway keyword.operator.key-value.sway
12 | # ^ source.sway
13 | # ^^^ source.sway entity.name.type.numeric.sway
14 | # ^ source.sway
15 | # ^ source.sway keyword.operator.assignment.equal.sway
16 | # ^ source.sway
17 | # ^ source.sway constant.numeric.decimal.sway
18 | # ^ source.sway punctuation.comma.sway
19 | > demand: u64 = 0,
20 | #^^^^ source.sway
21 | # ^^^^^^ source.sway variable.other.sway
22 | # ^ source.sway keyword.operator.key-value.sway
23 | # ^ source.sway
24 | # ^^^ source.sway entity.name.type.numeric.sway
25 | # ^ source.sway
26 | # ^ source.sway keyword.operator.assignment.equal.sway
27 | # ^ source.sway
28 | # ^ source.sway constant.numeric.decimal.sway
29 | # ^ source.sway punctuation.comma.sway
30 | > name: str[4] = "test",
31 | #^^^^ source.sway
32 | # ^^^^ source.sway variable.other.sway
33 | # ^ source.sway keyword.operator.key-value.sway
34 | # ^ source.sway
35 | # ^^^ source.sway entity.name.type.primitive.sway
36 | # ^ source.sway punctuation.brackets.square.sway
37 | # ^ source.sway constant.numeric.decimal.sway
38 | # ^ source.sway punctuation.brackets.square.sway
39 | # ^ source.sway
40 | # ^ source.sway keyword.operator.assignment.equal.sway
41 | # ^ source.sway
42 | # ^ source.sway string.quoted.double.sway punctuation.definition.string.sway
43 | # ^^^^ source.sway string.quoted.double.sway
44 | # ^ source.sway string.quoted.double.sway punctuation.definition.string.sway
45 | # ^ source.sway punctuation.comma.sway
46 | >}
47 | #^ source.sway punctuation.brackets.curly.sway
48 | >fn main() {
49 | #^^ source.sway meta.function.definition.sway keyword.other.fn.sway
50 | # ^ source.sway meta.function.definition.sway
51 | # ^^^^ source.sway meta.function.definition.sway entity.name.function.sway
52 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
53 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
54 | # ^ source.sway meta.function.definition.sway
55 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
56 | >}
57 | #^ source.sway punctuation.brackets.curly.sway
58 | >
--------------------------------------------------------------------------------
/client/src/commands/openDotGraph.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import * as vscode from 'vscode';
3 | import { EXTENSION_ROOT, getExtensionPath } from '../config';
4 | import { GraphKind, visualize } from '../interface/visualize';
5 | import { addFilePrefix, log } from '../util/util';
6 |
7 | export default async function openDotGraph(
8 | filePath: string,
9 | graphKind: GraphKind
10 | ) {
11 | try {
12 | const dotContents = await visualize(addFilePrefix(filePath), graphKind);
13 | if (dotContents) {
14 | const nodeModulesPath = vscode.Uri.file(
15 | path.join(getExtensionPath(), 'node_modules')
16 | );
17 |
18 | const panel = vscode.window.createWebviewPanel(
19 | `${EXTENSION_ROOT}.crate-graph`,
20 | `${EXTENSION_ROOT} build plan graph`,
21 | vscode.ViewColumn.Two,
22 | {
23 | enableScripts: true,
24 | retainContextWhenHidden: true,
25 | localResourceRoots: [nodeModulesPath],
26 | }
27 | );
28 | const uri = panel.webview.asWebviewUri(nodeModulesPath);
29 |
30 | const html = `
31 |
32 |
33 |
34 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
70 |
71 | `;
72 |
73 | panel.webview.html = html;
74 | } else {
75 | log.error(`No ${graphKind} graph found for ${filePath}`);
76 | }
77 | } catch (error) {
78 | log.error(`Failed to open ${graphKind} graph for ${filePath}`, error);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/client/src/config.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { log } from './util/util';
3 |
4 | export const EXTENSION_ID = 'fuellabs.sway-vscode-plugin';
5 | export const EXTENSION_ROOT = 'sway-lsp';
6 |
7 | export const getExtension = () => vscode.extensions.getExtension(EXTENSION_ID);
8 |
9 | export const getExtensionPath = () => getExtension()!.extensionPath;
10 |
11 | export const getExtensionManifest = () => getExtension()!.packageJSON;
12 |
13 | export class Config {
14 | private readonly requiresReloadOpts = ['debug', 'diagnostic'].map(
15 | opt => `${EXTENSION_ROOT}.${opt}`
16 | );
17 |
18 | readonly package: {
19 | version: string;
20 | } = getExtensionManifest();
21 |
22 | readonly globalStorageUri: vscode.Uri;
23 |
24 | constructor(ctx: vscode.ExtensionContext) {
25 | this.globalStorageUri = ctx.globalStorageUri;
26 | vscode.workspace.onDidChangeConfiguration(
27 | this.onDidChangeConfiguration,
28 | this,
29 | ctx.subscriptions
30 | );
31 | this.refreshLogging();
32 | }
33 |
34 | private refreshLogging() {
35 | log.setEnabled(this.traceExtension);
36 | log.info('Starting the Sway Language Client and Server');
37 | log.info('Extension version:', this.package.version);
38 |
39 | const cfg = Object.entries(this.cfg).filter(
40 | ([_, val]) => !(val instanceof Function)
41 | );
42 | log.info('Using configuration', Object.fromEntries(cfg));
43 | }
44 |
45 | private async onDidChangeConfiguration(
46 | event: vscode.ConfigurationChangeEvent
47 | ) {
48 | this.refreshLogging();
49 |
50 | const requiresReloadOpt = this.requiresReloadOpts.find(opt =>
51 | event.affectsConfiguration(opt)
52 | );
53 |
54 | if (!requiresReloadOpt) return;
55 |
56 | const userResponse = await vscode.window.showInformationMessage(
57 | `Changing "${requiresReloadOpt}" requires a reload`,
58 | 'Reload now'
59 | );
60 |
61 | if (userResponse === 'Reload now') {
62 | await vscode.commands.executeCommand('workbench.action.reloadWindow');
63 | }
64 | }
65 |
66 | // We don't do runtime config validation here for simplicity. More on stackoverflow:
67 | // https://stackoverflow.com/questions/60135780/what-is-the-best-way-to-type-check-the-configuration-for-vscode-extension
68 |
69 | private get cfg(): vscode.WorkspaceConfiguration {
70 | return vscode.workspace.getConfiguration(EXTENSION_ROOT);
71 | }
72 |
73 | /**
74 | * Beware that postfix `!` operator erases both `null` and `undefined`.
75 | * This is why the following doesn't work as expected:
76 | *
77 | * ```ts
78 | * const nullableNum = vscode
79 | * .workspace
80 | * .getConfiguration
81 | * .getConfiguration("sway-lsp")
82 | * .get(path)!;
83 | *
84 | * // What happens is that type of `nullableNum` is `number` but not `null | number`:
85 | * const fullFledgedNum: number = nullableNum;
86 | * ```
87 | * So this getter handles this quirk by not requiring the caller to use postfix `!`
88 | */
89 | private get(path: string): T {
90 | return this.cfg.get(path)!;
91 | }
92 |
93 | get binPath() {
94 | return this.get('diagnostic.binPath');
95 | }
96 |
97 | get disableLsp() {
98 | return this.get('diagnostic.disableLsp');
99 | }
100 |
101 | get traceExtension() {
102 | return this.get('trace.extension');
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/client/src/palettes.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import * as vscode from 'vscode';
3 | import forcBuild from './commands/forcBuild';
4 | import forcRun from './commands/forcRun';
5 | import forcTest from './commands/forcTest';
6 | import goToLocation from './commands/goToLocation';
7 | import installServer from './commands/installServer';
8 | import openAstFile from './commands/openAstFile';
9 | import openDotGraph from './commands/openDotGraph';
10 | import peekLocations from './commands/peekLocations';
11 | import startFuelCore from './commands/startFuelCore';
12 | import stopFuelCore from './commands/stopFuelCore';
13 | import { Config } from './config';
14 |
15 | interface CommandPalette {
16 | command: string;
17 | callback: (args?: any) => Promise;
18 | }
19 |
20 | export class CommandPalettes {
21 | constructor(readonly config: Config) {}
22 |
23 | get(): CommandPalette[] {
24 | return [
25 | {
26 | command: 'sway.runScript',
27 | callback: async () => {
28 | const currentTabDirectory = path.dirname(
29 | vscode.window.activeTextEditor.document.fileName
30 | );
31 | forcRun(currentTabDirectory);
32 | },
33 | },
34 | {
35 | command: 'sway.runTests',
36 | callback: async () => {
37 | const currentTabDirectory = path.dirname(
38 | vscode.window.activeTextEditor.document.fileName
39 | );
40 | forcTest(currentTabDirectory);
41 | },
42 | },
43 | {
44 | command: 'sway.forcBuild',
45 | callback: async () => {
46 | const currentTabDirectory = path.dirname(
47 | vscode.window.activeTextEditor.document.fileName
48 | );
49 | forcBuild(currentTabDirectory);
50 | },
51 | },
52 | {
53 | command: 'sway.startFuelCore',
54 | callback: async () => startFuelCore(),
55 | },
56 | {
57 | command: 'sway.stopFuelCore',
58 | callback: async () => stopFuelCore(),
59 | },
60 | {
61 | command: 'sway.showLexedAst',
62 | callback: async () => {
63 | const currentFile = vscode.window.activeTextEditor.document.fileName;
64 | await openAstFile(currentFile, 'lexed');
65 | },
66 | },
67 | {
68 | command: 'sway.showParsedAst',
69 | callback: async () => {
70 | const currentFile = vscode.window.activeTextEditor.document.fileName;
71 | await openAstFile(currentFile, 'parsed');
72 | },
73 | },
74 | {
75 | command: 'sway.showTypedAst',
76 | callback: async () => {
77 | const currentFile = vscode.window.activeTextEditor.document.fileName;
78 | await openAstFile(currentFile, 'typed');
79 | },
80 | },
81 | {
82 | command: 'sway.viewBuildPlan',
83 | callback: async () => {
84 | const currentFile = vscode.window.activeTextEditor.document.fileName;
85 | await openDotGraph(currentFile, 'build_plan');
86 | },
87 | },
88 | {
89 | command: 'sway.installServer',
90 | callback: async () => installServer(),
91 | },
92 | {
93 | command: 'sway.goToLocation',
94 | callback: goToLocation,
95 | },
96 | {
97 | command: 'sway.peekLocations',
98 | callback: peekLocations,
99 | },
100 | ];
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ## [0.3.5](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.3.5) - 2024-06-25 05:32:50
4 |
5 | ## What's Changed
6 | * chore: send client name with initialization request by @sdankel in https://github.com/FuelLabs/sway-vscode-plugin/pull/187
7 |
8 |
9 | **Full Changelog**: https://github.com/FuelLabs/sway-vscode-plugin/compare/0.3.4...0.3.5
10 |
11 | ### Chores
12 |
13 | - general:
14 | - send client name with initialization request (#187) ([b4b622d](https://github.com/FuelLabs/sway-vscode-plugin/commit/b4b622d0daa0a54edd5e5c46e6c6d91cf5d9b97a)) ([#187](https://github.com/FuelLabs/sway-vscode-plugin/pull/187))
15 |
16 | ## [0.3.4](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.3.4) - 2024-05-26 23:46:40
17 |
18 | ## What's Changed
19 | * ci: Use fuel service user token by @sdankel in https://github.com/FuelLabs/sway-vscode-plugin/pull/184
20 | * fix: Only send OnEnter for sway files by @sdankel in https://github.com/FuelLabs/sway-vscode-plugin/pull/183
21 | * chore: bump to 0.3.4 by @sdankel in https://github.com/FuelLabs/sway-vscode-plugin/pull/185
22 |
23 |
24 | **Full Changelog**: https://github.com/FuelLabs/sway-vscode-plugin/compare/0.3.3...0.3.4
25 |
26 | ### Bug Fixes
27 |
28 | - general:
29 | - Only send OnEnter for sway files (#183) ([983aee6](https://github.com/FuelLabs/sway-vscode-plugin/commit/983aee6d83ac1a5e4701ff312b8e0b5b8446ec33)) ([#183](https://github.com/FuelLabs/sway-vscode-plugin/pull/183))
30 |
31 | ### Chores
32 |
33 | - general:
34 | - bump to 0.3.4 (#185) ([6de0cd6](https://github.com/FuelLabs/sway-vscode-plugin/commit/6de0cd6a8df1b103276c8caf1ceffaf860f8c88b)) ([#185](https://github.com/FuelLabs/sway-vscode-plugin/pull/185))
35 |
36 | ## [0.3.3](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.3.3) - 2024-04-18 23:43:25
37 |
38 | ## [0.3.2](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.3.2) - 2024-04-17 20:04:11
39 |
40 | ## [0.3.1](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.3.1) - 2024-03-01 20:38:57
41 |
42 | ## [0.3.0](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.3.0) - 2024-02-27 23:35:46
43 |
44 | ## [0.2.16](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.16) - 2023-11-28 21:57:20
45 |
46 | ## [0.2.15](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.15) - 2023-08-01 03:58:38
47 |
48 | ## [0.2.14](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.14) - 2023-05-04 20:01:53
49 |
50 | ## [0.2.13](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.13) - 2023-03-22 04:17:52
51 |
52 | ## [0.2.12](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.12) - 2023-03-21 00:02:00
53 |
54 | ## [0.2.11](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.11) - 2023-03-20 23:15:58
55 |
56 | ## [0.2.9](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.9) - 2023-01-25 02:19:45
57 |
58 | ## [0.2.8](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.8) - 2023-01-11 22:57:29
59 |
60 | ## [0.2.7](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.7) - 2022-12-06 07:11:44
61 |
62 | ## [0.2.6](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.6) - 2022-12-06 06:14:38
63 |
64 | ## [0.2.5](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.5) - 2022-10-31 00:31:49
65 |
66 | ## [0.2.4](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.4) - 2022-08-25 23:36:41
67 |
68 | ## [0.2.3](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.3) - 2022-06-16 20:57:27
69 |
70 | ## [0.2.2](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.2) - 2022-04-10 11:26:49
71 |
72 | ## [0.2.1](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.1) - 2022-03-04 02:02:54
73 |
74 | ## [0.2.0](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.2.0) - 2022-02-27 22:46:34
75 |
76 | ## [0.1.0](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.1.0) - 2021-12-25 14:17:08
77 |
78 | ## [0.0.1](https://github.com/FuelLabs/sway-vscode-plugin/releases/tag/0.0.1) - 2021-12-22 13:51:35
79 |
80 | Initial release.
81 |
82 | \* *This CHANGELOG was automatically generated by [auto-generate-changelog](https://github.com/BobAnkh/auto-generate-changelog)*
83 |
--------------------------------------------------------------------------------
/client/src/program.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import * as path from 'path';
3 | // import * as fuels from 'typechain-target-fuels';
4 | import {
5 | Event,
6 | EventEmitter,
7 | ProviderResult,
8 | TreeDataProvider,
9 | TreeItem,
10 | TreeItemCollapsibleState,
11 | window,
12 | } from 'vscode';
13 |
14 | const ABI_FILE_SUFFIX = '-abi.json';
15 |
16 | export class ProgramProvider implements TreeDataProvider {
17 | private _onDidChangeTreeData: EventEmitter =
18 | new EventEmitter();
19 | readonly onDidChangeTreeData: Event =
20 | this._onDidChangeTreeData.event;
21 |
22 | constructor(
23 | private workspaceRoot: string | undefined,
24 | readonly type: ProgramType
25 | ) {}
26 |
27 | refresh(): void {
28 | this._onDidChangeTreeData.fire();
29 | }
30 |
31 | getTreeItem(element: TreeItem): TreeItem {
32 | return element;
33 | }
34 |
35 | getChildren(contract?: Function | Program): ProviderResult {
36 | if (!this.workspaceRoot) {
37 | window.showInformationMessage('No contract in empty workspace');
38 | return Promise.resolve([]);
39 | }
40 |
41 | return contract
42 | ? Promise.resolve(contract['children'])
43 | : this.getPrograms();
44 | }
45 |
46 | /**
47 | * Reads contracts from the ABIs.
48 | * @returns array of contracts
49 | */
50 | private async getPrograms(): Promise {
51 | const allFiles = getAllFiles(this.workspaceRoot, []);
52 | const swayFilePaths = allFiles.filter(file => file.endsWith('.sw'));
53 | const forcTomlFilePaths = allFiles.filter(file =>
54 | file.endsWith('Forc.toml')
55 | );
56 | const abiFilePaths = allFiles.filter(file =>
57 | file.endsWith(ABI_FILE_SUFFIX)
58 | );
59 | const programs = abiFilePaths.map(filepath => {
60 | const contractName = path
61 | .parse(filepath)
62 | .base.replace(ABI_FILE_SUFFIX, '');
63 |
64 | // This is assuming that there is only one sway contract in the same directory as a Forc.toml
65 | const forcFilePath = forcTomlFilePaths.find(forcFilePath =>
66 | fs.readFileSync(forcFilePath).toString().includes(contractName)
67 | );
68 |
69 | // Find out the program type of the sway file
70 | const swayFilePath = swayFilePaths.find(swayFilePath => {
71 | return swayFilePath.startsWith(path.parse(forcFilePath).dir);
72 | });
73 | const swayFileMatchesType = fs
74 | .readFileSync(swayFilePath)
75 | .toString()
76 | .startsWith(this.type);
77 | if (!swayFileMatchesType) return undefined;
78 |
79 | // Attach the source file path to each function node in addition to the contract node
80 | const buffer = fs.readFileSync(filepath);
81 | const abi: Object[] = JSON.parse(buffer.toString());
82 | const functions = abi
83 | .filter(obj => obj['type'] === 'function')
84 | .map(func => new Function(func['name'], swayFilePath));
85 |
86 | return new Program(contractName, swayFilePath, functions, this.type);
87 | });
88 |
89 | // Filter out programs that do not match the given type
90 | return programs.filter(program => !!program);
91 | }
92 | }
93 |
94 | /**
95 | * Recursively finds all ABI files in the workspace
96 | * @param dirPath path to current directory
97 | * @param arrayOfFiles array of files to search
98 | * @returns list of all ABI file paths
99 | */
100 | const getAllFiles = (dirPath: string, arrayOfFiles: string[]): string[] => {
101 | let files = fs.readdirSync(dirPath);
102 |
103 | arrayOfFiles = arrayOfFiles || [];
104 |
105 | files.forEach(function (file) {
106 | if (fs.statSync(dirPath + '/' + file).isDirectory()) {
107 | arrayOfFiles = getAllFiles(dirPath + '/' + file, arrayOfFiles);
108 | } else {
109 | arrayOfFiles.push(path.join(dirPath, '/', file));
110 | }
111 | });
112 |
113 | return arrayOfFiles;
114 | };
115 |
116 | export type ProgramType = 'contract' | 'script' | 'predicate';
117 |
118 | export class Program extends TreeItem {
119 | constructor(
120 | public readonly name: string,
121 | public readonly sourceFilePath: string,
122 | public readonly children: Function[],
123 | public readonly type?: ProgramType
124 | ) {
125 | super(
126 | name,
127 | children
128 | ? TreeItemCollapsibleState.Expanded
129 | : TreeItemCollapsibleState.None
130 | );
131 |
132 | this.label = name;
133 | this.tooltip = name;
134 | }
135 |
136 | contextValue = this.type ?? 'program';
137 | }
138 |
139 | export class Function extends TreeItem {
140 | constructor(
141 | public readonly label: string,
142 | public readonly sourceFilePath: string
143 | ) {
144 | super(label, TreeItemCollapsibleState.None);
145 |
146 | this.tooltip = this.label;
147 | }
148 |
149 | contextValue = 'function';
150 | }
151 |
--------------------------------------------------------------------------------
/client/test/syntaxes/smo_opcode.sw.snap:
--------------------------------------------------------------------------------
1 | >script;
2 | #^^^^^^ source.sway source.sway meta.attribute.sway
3 | # ^ source.sway
4 | >
5 | >use std::constants::ZERO_B256;
6 | #^^^ source.sway meta.use.sway keyword.other.sway
7 | # ^ source.sway meta.use.sway
8 | # ^^^ source.sway meta.use.sway entity.name.namespace.sway
9 | # ^^ source.sway meta.use.sway keyword.operator.namespace.sway
10 | # ^^^^^^^^^ source.sway meta.use.sway entity.name.namespace.sway
11 | # ^^ source.sway meta.use.sway keyword.operator.namespace.sway
12 | # ^^^^^^^^^ source.sway meta.use.sway
13 | # ^ source.sway meta.use.sway punctuation.semi.sway
14 | >
15 | >fn main() -> bool {
16 | #^^ source.sway meta.function.definition.sway keyword.other.fn.sway
17 | # ^ source.sway meta.function.definition.sway
18 | # ^^^^ source.sway meta.function.definition.sway entity.name.function.sway
19 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
20 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
21 | # ^ source.sway meta.function.definition.sway
22 | # ^^ source.sway meta.function.definition.sway keyword.operator.arrow.skinny.sway
23 | # ^ source.sway meta.function.definition.sway
24 | # ^^^^ source.sway meta.function.definition.sway entity.name.type.primitive.sway
25 | # ^ source.sway meta.function.definition.sway
26 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
27 | > asm(recipient: ZERO_B256, msg_len: 0, output: 0, coins: 0) {
28 | #^^^^ source.sway
29 | # ^^^ source.sway meta.asm.definition.sway meta.attribute.asm.sway
30 | # ^ source.sway meta.asm.definition.sway punctuation.brackets.round.sway
31 | # ^^^^^^^^^ source.sway meta.asm.definition.sway variable.other.sway
32 | # ^ source.sway meta.asm.definition.sway keyword.operator.key-value.sway
33 | # ^ source.sway meta.asm.definition.sway
34 | # ^^^^^^^^^ source.sway meta.asm.definition.sway constant.other.caps.sway
35 | # ^ source.sway meta.asm.definition.sway punctuation.comma.sway
36 | # ^ source.sway meta.asm.definition.sway
37 | # ^^^^^^^ source.sway meta.asm.definition.sway variable.other.sway
38 | # ^ source.sway meta.asm.definition.sway keyword.operator.key-value.sway
39 | # ^ source.sway meta.asm.definition.sway
40 | # ^ source.sway meta.asm.definition.sway constant.numeric.decimal.sway
41 | # ^ source.sway meta.asm.definition.sway punctuation.comma.sway
42 | # ^ source.sway meta.asm.definition.sway
43 | # ^^^^^^ source.sway meta.asm.definition.sway variable.other.sway
44 | # ^ source.sway meta.asm.definition.sway keyword.operator.key-value.sway
45 | # ^ source.sway meta.asm.definition.sway
46 | # ^ source.sway meta.asm.definition.sway constant.numeric.decimal.sway
47 | # ^ source.sway meta.asm.definition.sway punctuation.comma.sway
48 | # ^ source.sway meta.asm.definition.sway
49 | # ^^^^^ source.sway meta.asm.definition.sway variable.other.sway
50 | # ^ source.sway meta.asm.definition.sway keyword.operator.key-value.sway
51 | # ^ source.sway meta.asm.definition.sway
52 | # ^ source.sway meta.asm.definition.sway constant.numeric.decimal.sway
53 | # ^ source.sway meta.asm.definition.sway punctuation.brackets.round.sway
54 | # ^ source.sway meta.asm.definition.sway
55 | # ^ source.sway meta.asm.definition.sway punctuation.brackets.curly.sway
56 | > smo recipient msg_len coins output;
57 | #^^^^^^^^ source.sway
58 | # ^^^ source.sway variable.other.sway
59 | # ^ source.sway
60 | # ^^^^^^^^^ source.sway variable.other.sway
61 | # ^ source.sway
62 | # ^^^^^^^ source.sway variable.other.sway
63 | # ^ source.sway
64 | # ^^^^^ source.sway variable.other.sway
65 | # ^ source.sway
66 | # ^^^^^^ source.sway variable.other.sway
67 | # ^ source.sway punctuation.semi.sway
68 | > }
69 | #^^^^ source.sway
70 | # ^ source.sway punctuation.brackets.curly.sway
71 | > true
72 | #^^^^ source.sway
73 | # ^^^^ source.sway constant.language.bool.sway
74 | >}
75 | #^ source.sway punctuation.brackets.curly.sway
76 | >
--------------------------------------------------------------------------------
/client/src/main.ts:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 | import { lt } from 'semver';
3 | import { promisify } from 'util';
4 | import { commands, ExtensionContext, window, workspace } from 'vscode';
5 | import * as lc from 'vscode-languageclient/node';
6 | import { createClient, getClient } from './client';
7 | import {
8 | Config,
9 | EXTENSION_ROOT as EXTENSION_ROOT,
10 | getExtensionManifest,
11 | } from './config';
12 | import { onEnter } from './interface/onEnter';
13 | import { CommandPalettes } from './palettes';
14 | import updateFuelCoreStatus from './status_bar/fuelCoreStatus';
15 | import { log, Terminal } from './util/util';
16 |
17 | const LSP_EXECUTABLE_NAME = 'forc-lsp';
18 |
19 | export async function activate(context: ExtensionContext) {
20 | const config = new Config(context);
21 |
22 | // Register all command palettes
23 | const commandPalettes = new CommandPalettes(config).get();
24 | context.subscriptions.push(
25 | ...commandPalettes.map(({ command, callback }) =>
26 | commands.registerCommand(command, callback)
27 | )
28 | );
29 |
30 | // Start a recurring task to keep fuel-core status updated
31 | setInterval(updateFuelCoreStatus, 1000);
32 |
33 | if (config.disableLsp) {
34 | log.info('Sway Language Server is disabled. Exiting...');
35 | return;
36 | }
37 |
38 | // Listen for did_change events for on_enter capabilities.
39 | workspace.onDidChangeTextDocument(
40 | async changeEvent => await onEnter(changeEvent)
41 | );
42 |
43 | try {
44 | const client = createClient(
45 | getClientOptions(),
46 | await getServerOptions(config)
47 | );
48 |
49 | // Start the client. This will also launch the server
50 | await client.start();
51 |
52 | log.info('Client has connected to the Sway Language Server Successfully!');
53 | } catch (error) {
54 | log.error(error);
55 | log.error(
56 | 'Unable to start the Sway Language Server. Please check the logs for more information.'
57 | );
58 | }
59 | }
60 |
61 | export function deactivate(): Thenable | undefined {
62 | const client = getClient();
63 | if (!client) {
64 | return undefined;
65 | }
66 | return client.stop();
67 | }
68 |
69 | async function getServerOptions(config: Config): Promise {
70 | // Look for the default executable in FUELUP_HOME if it exists, otherwise look for it in the PATH.
71 | const defaultExecutable = process.env.FUELUP_HOME
72 | ? `${process.env.FUELUP_HOME}/bin/${LSP_EXECUTABLE_NAME}`
73 | : LSP_EXECUTABLE_NAME;
74 |
75 | // Use the settings override path if provided, otherwise use the default executable.
76 | const settingsExecutable = config.binPath;
77 | const executable = settingsExecutable || defaultExecutable;
78 |
79 | // Check if the executable exists.
80 | try {
81 | let versionRes = await promisify(exec)(`${executable} --version`);
82 | let versionStr = versionRes.stdout.trim();
83 | log.info(`Server executable version: ${versionStr}`);
84 |
85 | let version = versionStr.split(' ')[1];
86 | let latestForcVersion = getExtensionManifest().latestForcVersion;
87 | log.info(`Latest forc version: ${latestForcVersion}`);
88 |
89 | if (lt(version, latestForcVersion)) {
90 | window
91 | .showInformationMessage(
92 | 'A new version of the Sway Language Server is available.',
93 | 'Update',
94 | 'Later'
95 | )
96 | .then(async selection => {
97 | if (selection === 'Update') {
98 | Terminal.Sway.execute('fuelup update');
99 | }
100 | });
101 | }
102 | } catch (error) {
103 | if (!!settingsExecutable) {
104 | const updateMessage =
105 | 'Update the setting "sway-lsp.diagnostic.binPath" either to a valid path to a forc-lsp executable, or leave it empty to use the executable to which your $PATH resolves.';
106 | window
107 | .showErrorMessage(
108 | 'The Sway Language Server is not installed at the path defined in your Extension Settings.',
109 | 'Edit Setting',
110 | 'Later'
111 | )
112 | .then(async selection => {
113 | if (selection === 'Edit Setting') {
114 | window.showInformationMessage(updateMessage);
115 | commands.executeCommand(
116 | 'workbench.action.openWorkspaceSettings',
117 | 'sway-lsp.diagnostic.binPath'
118 | );
119 | }
120 | });
121 | throw Error(`Missing executable: ${LSP_EXECUTABLE_NAME}\
122 | \n\nThe VSCode setting "sway-lsp.diagnostic.binPath" is set to an invalid path: "${settingsExecutable}"
123 | \n${updateMessage}`);
124 | } else {
125 | window
126 | .showErrorMessage(
127 | 'The Sway Language Server is not installed. Would you like to install it?',
128 | 'Yes',
129 | 'No'
130 | )
131 | .then(async selection => {
132 | if (selection === 'Yes') {
133 | window.showInformationMessage(
134 | 'Follow the instructions in the terminal to install the Sway Language Server, then reload the window.'
135 | );
136 | commands.executeCommand('sway.installServer');
137 | }
138 | });
139 | throw Error(`Missing executable: ${LSP_EXECUTABLE_NAME}\
140 | \n\nYou may need to install the fuel toolchain or add ${process.env.HOME}/.fuelup/bin your path. Try running:\
141 | \n\ncurl --proto '=https' --tlsv1.2 -sSf https://install.fuel.network/fuelup-init.sh | sh\
142 | \n\nOr read about fuelup for more information: https://github.com/FuelLabs/fuelup\n`);
143 | }
144 | }
145 |
146 | // Get the full path to the server executable.
147 | const { stdout: executablePath } = await promisify(exec)(
148 | `which ${executable}`
149 | );
150 | const command = executablePath.trim();
151 | log.info(`Using server executable: ${command}`);
152 |
153 | const serverExecutable: lc.Executable = {
154 | command: `RUST_BACKTRACE=FULL ${command}`,
155 | options: {
156 | shell: true,
157 | },
158 | };
159 |
160 | return {
161 | run: serverExecutable,
162 | debug: serverExecutable,
163 | transport: lc.TransportKind.stdio,
164 | };
165 | }
166 |
167 | function getClientOptions(): lc.LanguageClientOptions {
168 | // Options to control the language client
169 | const clientOptions: lc.LanguageClientOptions = {
170 | // Register the server for plain text documents
171 | documentSelector: [
172 | { scheme: 'file', language: 'sway' },
173 | { scheme: 'untitled', language: 'sway' },
174 | ],
175 | synchronize: {
176 | // Notify the server about file changes to *.sw files contained in the workspace
177 | fileEvents: [
178 | workspace.createFileSystemWatcher('**/.sw'),
179 | workspace.createFileSystemWatcher('**/*.sw'),
180 | ],
181 | },
182 | initializationOptions: {
183 | ...workspace.getConfiguration(EXTENSION_ROOT),
184 | client: 'vscode',
185 | },
186 | markdown: {
187 | isTrusted: true,
188 | supportHtml: true,
189 | },
190 | };
191 |
192 | return clientOptions;
193 | }
194 |
--------------------------------------------------------------------------------
/client/test/syntaxes/match_expressions_mismatched.sw.snap:
--------------------------------------------------------------------------------
1 | >script;
2 | #^^^^^^ source.sway source.sway meta.attribute.sway
3 | # ^ source.sway
4 | >
5 | >struct MyStruct {
6 | #^^^^^^ source.sway keyword.declaration.struct.sway
7 | # ^ source.sway
8 | # ^^^^^^^^ source.sway entity.name.type.struct.sway
9 | # ^ source.sway
10 | # ^ source.sway punctuation.brackets.curly.sway
11 | > a: u64,
12 | #^^^^ source.sway
13 | # ^ source.sway variable.other.sway
14 | # ^ source.sway keyword.operator.key-value.sway
15 | # ^ source.sway
16 | # ^^^ source.sway entity.name.type.numeric.sway
17 | # ^ source.sway punctuation.comma.sway
18 | > b: u64,
19 | #^^^^ source.sway
20 | # ^ source.sway variable.other.sway
21 | # ^ source.sway keyword.operator.key-value.sway
22 | # ^ source.sway
23 | # ^^^ source.sway entity.name.type.numeric.sway
24 | # ^ source.sway punctuation.comma.sway
25 | >}
26 | #^ source.sway punctuation.brackets.curly.sway
27 | >
28 | >enum MyEnum {
29 | #^^^^ source.sway keyword.declaration.enum.sway
30 | # ^ source.sway
31 | # ^^^^^^ source.sway entity.name.type.enum.sway
32 | # ^ source.sway
33 | # ^ source.sway punctuation.brackets.curly.sway
34 | > Variant1: (),
35 | #^^^^ source.sway
36 | # ^^^^^^^^ source.sway entity.name.type.sway
37 | # ^ source.sway keyword.operator.key-value.sway
38 | # ^ source.sway
39 | # ^ source.sway punctuation.brackets.round.sway
40 | # ^ source.sway punctuation.brackets.round.sway
41 | # ^ source.sway punctuation.comma.sway
42 | > Variant2: u64,
43 | #^^^^ source.sway
44 | # ^^^^^^^^ source.sway entity.name.type.sway
45 | # ^ source.sway keyword.operator.key-value.sway
46 | # ^ source.sway
47 | # ^^^ source.sway entity.name.type.numeric.sway
48 | # ^ source.sway punctuation.comma.sway
49 | > Variant3: MyStruct,
50 | #^^^^ source.sway
51 | # ^^^^^^^^ source.sway entity.name.type.sway
52 | # ^ source.sway keyword.operator.key-value.sway
53 | # ^ source.sway
54 | # ^^^^^^^^ source.sway entity.name.type.sway
55 | # ^ source.sway punctuation.comma.sway
56 | >}
57 | #^ source.sway punctuation.brackets.curly.sway
58 | >
59 | >fn main() -> u64 {
60 | #^^ source.sway meta.function.definition.sway keyword.other.fn.sway
61 | # ^ source.sway meta.function.definition.sway
62 | # ^^^^ source.sway meta.function.definition.sway entity.name.function.sway
63 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
64 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
65 | # ^ source.sway meta.function.definition.sway
66 | # ^^ source.sway meta.function.definition.sway keyword.operator.arrow.skinny.sway
67 | # ^ source.sway meta.function.definition.sway
68 | # ^^^ source.sway meta.function.definition.sway entity.name.type.numeric.sway
69 | # ^ source.sway meta.function.definition.sway
70 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
71 | > let x = MyEnum::Variant1;
72 | #^^^^ source.sway
73 | # ^^^ source.sway storage.modifier.sway
74 | # ^ source.sway
75 | # ^ source.sway variable.other.sway
76 | # ^ source.sway
77 | # ^ source.sway keyword.operator.assignment.equal.sway
78 | # ^ source.sway
79 | # ^^^^^^ source.sway entity.name.type.sway
80 | # ^^ source.sway keyword.operator.namespace.sway
81 | # ^^^^^^^^ source.sway entity.name.type.sway
82 | # ^ source.sway punctuation.semi.sway
83 | > let y = MyEnum::Variant2(5);
84 | #^^^^ source.sway
85 | # ^^^ source.sway storage.modifier.sway
86 | # ^ source.sway
87 | # ^ source.sway variable.other.sway
88 | # ^ source.sway
89 | # ^ source.sway keyword.operator.assignment.equal.sway
90 | # ^ source.sway
91 | # ^^^^^^ source.sway entity.name.type.sway
92 | # ^^ source.sway keyword.operator.namespace.sway
93 | # ^^^^^^^^ source.sway meta.function.call.sway entity.name.function.sway
94 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
95 | # ^ source.sway meta.function.call.sway constant.numeric.decimal.sway
96 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
97 | # ^ source.sway punctuation.semi.sway
98 | > let z = MyEnum::Variant3(MyStruct {
99 | #^^^^ source.sway
100 | # ^^^ source.sway storage.modifier.sway
101 | # ^ source.sway
102 | # ^ source.sway variable.other.sway
103 | # ^ source.sway
104 | # ^ source.sway keyword.operator.assignment.equal.sway
105 | # ^ source.sway
106 | # ^^^^^^ source.sway entity.name.type.sway
107 | # ^^ source.sway keyword.operator.namespace.sway
108 | # ^^^^^^^^ source.sway meta.function.call.sway entity.name.function.sway
109 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
110 | # ^^^^^^^^ source.sway meta.function.call.sway entity.name.type.sway
111 | # ^ source.sway meta.function.call.sway
112 | # ^ source.sway meta.function.call.sway punctuation.brackets.curly.sway
113 | > a: 0, b: 1
114 | #^^^^^^^^ source.sway meta.function.call.sway
115 | # ^ source.sway meta.function.call.sway variable.other.sway
116 | # ^ source.sway meta.function.call.sway keyword.operator.key-value.sway
117 | # ^ source.sway meta.function.call.sway
118 | # ^ source.sway meta.function.call.sway constant.numeric.decimal.sway
119 | # ^ source.sway meta.function.call.sway punctuation.comma.sway
120 | # ^ source.sway meta.function.call.sway
121 | # ^ source.sway meta.function.call.sway variable.other.sway
122 | # ^ source.sway meta.function.call.sway keyword.operator.key-value.sway
123 | # ^ source.sway meta.function.call.sway
124 | # ^ source.sway meta.function.call.sway constant.numeric.decimal.sway
125 | > });
126 | #^^^^ source.sway meta.function.call.sway
127 | # ^ source.sway meta.function.call.sway punctuation.brackets.curly.sway
128 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
129 | # ^ source.sway punctuation.semi.sway
130 | >
131 | > match y {
132 | #^^^^ source.sway
133 | # ^^^^^ source.sway keyword.control.sway
134 | # ^ source.sway
135 | # ^ source.sway variable.other.sway
136 | # ^ source.sway
137 | # ^ source.sway punctuation.brackets.curly.sway
138 | > MyEnum::Variant2(y) => y, _ => 10,
139 | #^^^^^^^^ source.sway
140 | # ^^^^^^ source.sway entity.name.type.sway
141 | # ^^ source.sway keyword.operator.namespace.sway
142 | # ^^^^^^^^ source.sway meta.function.call.sway entity.name.function.sway
143 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
144 | # ^ source.sway meta.function.call.sway variable.other.sway
145 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
146 | # ^ source.sway
147 | # ^^ source.sway keyword.operator.arrow.fat.sway
148 | # ^ source.sway
149 | # ^ source.sway variable.other.sway
150 | # ^ source.sway punctuation.comma.sway
151 | # ^ source.sway
152 | # ^ source.sway variable.other.sway
153 | # ^ source.sway
154 | # ^^ source.sway keyword.operator.arrow.fat.sway
155 | # ^ source.sway
156 | # ^^ source.sway constant.numeric.decimal.sway
157 | # ^ source.sway punctuation.comma.sway
158 | # ^^ source.sway
159 | > }
160 | #^^^^ source.sway
161 | # ^ source.sway punctuation.brackets.curly.sway
162 | >}
163 | #^ source.sway punctuation.brackets.curly.sway
164 | >
--------------------------------------------------------------------------------
/client/test/syntaxes/chained_if_let.sw.snap:
--------------------------------------------------------------------------------
1 | >script;
2 | #^^^^^^ source.sway source.sway meta.attribute.sway
3 | # ^ source.sway
4 | >
5 | >enum Result {
6 | #^^^^ source.sway keyword.declaration.enum.sway
7 | # ^ source.sway
8 | # ^^^^^^ source.sway entity.name.type.enum.sway
9 | # ^ source.sway punctuation.brackets.angle.sway
10 | # ^ source.sway entity.name.type.sway
11 | # ^ source.sway punctuation.comma.sway
12 | # ^ source.sway
13 | # ^ source.sway entity.name.type.sway
14 | # ^ source.sway punctuation.brackets.angle.sway
15 | # ^ source.sway
16 | # ^ source.sway punctuation.brackets.curly.sway
17 | > Ok: T,
18 | #^^^^ source.sway
19 | # ^^ source.sway entity.name.type.result.sway
20 | # ^ source.sway keyword.operator.key-value.sway
21 | # ^ source.sway
22 | # ^ source.sway entity.name.type.sway
23 | # ^ source.sway punctuation.comma.sway
24 | > Err: E,
25 | #^^^^ source.sway
26 | # ^^^ source.sway entity.name.type.result.sway
27 | # ^ source.sway keyword.operator.key-value.sway
28 | # ^ source.sway
29 | # ^ source.sway entity.name.type.sway
30 | # ^ source.sway punctuation.comma.sway
31 | >}
32 | #^ source.sway punctuation.brackets.curly.sway
33 | >
34 | >// should return 5
35 | #^^^^^^^^^^^^^^^^^^ source.sway comment.line.double-slash.sway
36 | >fn main() -> u64 {
37 | #^^ source.sway meta.function.definition.sway keyword.other.fn.sway
38 | # ^ source.sway meta.function.definition.sway
39 | # ^^^^ source.sway meta.function.definition.sway entity.name.function.sway
40 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
41 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
42 | # ^ source.sway meta.function.definition.sway
43 | # ^^ source.sway meta.function.definition.sway keyword.operator.arrow.skinny.sway
44 | # ^ source.sway meta.function.definition.sway
45 | # ^^^ source.sway meta.function.definition.sway entity.name.type.numeric.sway
46 | # ^ source.sway meta.function.definition.sway
47 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
48 | > let result_a = Result::Ok::(5u64);
49 | #^^^^ source.sway
50 | # ^^^ source.sway storage.modifier.sway
51 | # ^ source.sway
52 | # ^^^^^^^^ source.sway variable.other.sway
53 | # ^ source.sway
54 | # ^ source.sway keyword.operator.assignment.equal.sway
55 | # ^ source.sway
56 | # ^^^^^^ source.sway entity.name.type.sway
57 | # ^^ source.sway keyword.operator.namespace.sway
58 | # ^^ source.sway entity.name.type.result.sway
59 | # ^^ source.sway keyword.operator.namespace.sway
60 | # ^ source.sway punctuation.brackets.angle.sway
61 | # ^^^ source.sway entity.name.type.numeric.sway
62 | # ^ source.sway punctuation.comma.sway
63 | # ^ source.sway
64 | # ^^^^ source.sway entity.name.type.primitive.sway
65 | # ^ source.sway punctuation.brackets.angle.sway
66 | # ^ source.sway punctuation.brackets.round.sway
67 | # ^ source.sway constant.numeric.decimal.sway
68 | # ^^^ source.sway constant.numeric.decimal.sway entity.name.type.numeric.sway
69 | # ^ source.sway punctuation.brackets.round.sway
70 | # ^ source.sway punctuation.semi.sway
71 | > let result_b = Result::Err::(false);
72 | #^^^^ source.sway
73 | # ^^^ source.sway storage.modifier.sway
74 | # ^ source.sway
75 | # ^^^^^^^^ source.sway variable.other.sway
76 | # ^ source.sway
77 | # ^ source.sway keyword.operator.assignment.equal.sway
78 | # ^ source.sway
79 | # ^^^^^^ source.sway entity.name.type.sway
80 | # ^^ source.sway keyword.operator.namespace.sway
81 | # ^^^ source.sway entity.name.type.result.sway
82 | # ^^ source.sway keyword.operator.namespace.sway
83 | # ^ source.sway punctuation.brackets.angle.sway
84 | # ^^^ source.sway entity.name.type.numeric.sway
85 | # ^ source.sway punctuation.comma.sway
86 | # ^ source.sway
87 | # ^^^^ source.sway entity.name.type.primitive.sway
88 | # ^ source.sway punctuation.brackets.angle.sway
89 | # ^ source.sway punctuation.brackets.round.sway
90 | # ^^^^^ source.sway constant.language.bool.sway
91 | # ^ source.sway punctuation.brackets.round.sway
92 | # ^ source.sway punctuation.semi.sway
93 | >
94 | > if let Result::Err(a) = result_a {
95 | #^^^^ source.sway
96 | # ^^ source.sway keyword.control.sway
97 | # ^ source.sway
98 | # ^^^ source.sway storage.modifier.sway
99 | # ^ source.sway
100 | # ^^^^^^ source.sway entity.name.type.sway
101 | # ^^ source.sway keyword.operator.namespace.sway
102 | # ^^^ source.sway entity.name.type.result.sway
103 | # ^ source.sway punctuation.brackets.round.sway
104 | # ^ source.sway variable.other.sway
105 | # ^ source.sway punctuation.brackets.round.sway
106 | # ^ source.sway
107 | # ^ source.sway keyword.operator.assignment.equal.sway
108 | # ^ source.sway
109 | # ^^^^^^^^ source.sway variable.other.sway
110 | # ^ source.sway
111 | # ^ source.sway punctuation.brackets.curly.sway
112 | > 6
113 | #^^^^^^^^ source.sway
114 | # ^ source.sway constant.numeric.decimal.sway
115 | > } else if let Result::Ok(num) = result_b {
116 | #^^^^ source.sway
117 | # ^ source.sway punctuation.brackets.curly.sway
118 | # ^ source.sway
119 | # ^^^^ source.sway keyword.control.sway
120 | # ^ source.sway
121 | # ^^ source.sway keyword.control.sway
122 | # ^ source.sway
123 | # ^^^ source.sway storage.modifier.sway
124 | # ^ source.sway
125 | # ^^^^^^ source.sway entity.name.type.sway
126 | # ^^ source.sway keyword.operator.namespace.sway
127 | # ^^ source.sway entity.name.type.result.sway
128 | # ^ source.sway punctuation.brackets.round.sway
129 | # ^^^ source.sway variable.other.sway
130 | # ^ source.sway punctuation.brackets.round.sway
131 | # ^ source.sway
132 | # ^ source.sway keyword.operator.assignment.equal.sway
133 | # ^ source.sway
134 | # ^^^^^^^^ source.sway variable.other.sway
135 | # ^ source.sway
136 | # ^ source.sway punctuation.brackets.curly.sway
137 | > 10
138 | #^^^^^^^^ source.sway
139 | # ^^ source.sway constant.numeric.decimal.sway
140 | > } else if let Result::Ok(num) = result_a {
141 | #^^^^ source.sway
142 | # ^ source.sway punctuation.brackets.curly.sway
143 | # ^ source.sway
144 | # ^^^^ source.sway keyword.control.sway
145 | # ^ source.sway
146 | # ^^ source.sway keyword.control.sway
147 | # ^ source.sway
148 | # ^^^ source.sway storage.modifier.sway
149 | # ^ source.sway
150 | # ^^^^^^ source.sway entity.name.type.sway
151 | # ^^ source.sway keyword.operator.namespace.sway
152 | # ^^ source.sway entity.name.type.result.sway
153 | # ^ source.sway punctuation.brackets.round.sway
154 | # ^^^ source.sway variable.other.sway
155 | # ^ source.sway punctuation.brackets.round.sway
156 | # ^ source.sway
157 | # ^ source.sway keyword.operator.assignment.equal.sway
158 | # ^ source.sway
159 | # ^^^^^^^^ source.sway variable.other.sway
160 | # ^ source.sway
161 | # ^ source.sway punctuation.brackets.curly.sway
162 | > num
163 | #^^^^^^^^ source.sway
164 | # ^^^ source.sway variable.other.sway
165 | > } else {
166 | #^^^^ source.sway
167 | # ^ source.sway punctuation.brackets.curly.sway
168 | # ^ source.sway
169 | # ^^^^ source.sway keyword.control.sway
170 | # ^ source.sway
171 | # ^ source.sway punctuation.brackets.curly.sway
172 | > 42
173 | #^^^^^^^^ source.sway
174 | # ^^ source.sway constant.numeric.decimal.sway
175 | > }
176 | #^^^^ source.sway
177 | # ^ source.sway punctuation.brackets.curly.sway
178 | >}
179 | #^ source.sway punctuation.brackets.curly.sway
180 | >
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sway-vscode-plugin",
3 | "displayName": "Sway",
4 | "description": "Sway language extension for Visual Studio Code",
5 | "icon": "images/logo.png",
6 | "version": "0.3.6",
7 | "latestForcVersion": "0.63.5",
8 | "publisher": "FuelLabs",
9 | "license": "Apache-2.0",
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/FuelLabs/sway-vscode-plugin.git"
13 | },
14 | "scripts": {
15 | "vscode:prepublish": "npm run esbuild-base -- --minify",
16 | "esbuild-base": "esbuild ./client/src/main.ts --bundle --outfile=client/out/main.js --external:vscode --format=cjs --platform=node",
17 | "esbuild": "npm run esbuild-base -- --sourcemap",
18 | "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch=forever &",
19 | "pre:install-extension": "rm sway-vscode-plugin.vsix",
20 | "install-extension": "npm run package && code --install-extension sway-vscode-plugin.vsix --force",
21 | "format:check": "prettier --check 'client/src' 'snippets' 'syntaxes'",
22 | "format:fix": "prettier --write 'client/src' 'snippets' 'syntaxes'",
23 | "fix-syntaxes": "vscode-tmgrammar-snap --updateSnapshot client/test/syntaxes/*sw",
24 | "test-syntaxes": "vscode-tmgrammar-snap client/test/syntaxes/*sw",
25 | "package": "vsce package -o sway-vscode-plugin.vsix"
26 | },
27 | "engines": {
28 | "vscode": "^1.66.0"
29 | },
30 | "categories": [
31 | "Programming Languages",
32 | "Extension Packs",
33 | "Snippets",
34 | "Themes",
35 | "Debuggers"
36 | ],
37 | "main": "./client/out/main",
38 | "activationEvents": [
39 | "onDebug",
40 | "onLanguage:sway",
41 | "onView:sway",
42 | "onCommand:sway.runScript",
43 | "onCommand:sway.runTests",
44 | "onCommand:sway.forcBuild",
45 | "onCommand:sway.startFuelCore",
46 | "onCommand:sway.stopFuelCore",
47 | "onCommand:sway.showLexedAst",
48 | "onCommand:sway.showParsedAst",
49 | "onCommand:sway.showTypedAst",
50 | "onCommand:sway.viewBuildPlan",
51 | "onCommand:sway.installServer",
52 | "onCommand:sway.goToLocation",
53 | "onCommand:sway.peekLocations"
54 | ],
55 | "contributes": {
56 | "configuration": {
57 | "type": "object",
58 | "title": "sway-lsp",
59 | "properties": {
60 | "sway-lsp.trace.server": {
61 | "scope": "window",
62 | "type": "string",
63 | "description": "Traces the communication between VS Code and the Sway language server.",
64 | "enum": [
65 | "off",
66 | "messages",
67 | "verbose"
68 | ],
69 | "enumDescriptions": [
70 | "No traces",
71 | "Error only",
72 | "Full log"
73 | ],
74 | "default": "off"
75 | },
76 | "sway-lsp.trace.extension": {
77 | "description": "Enable logging of the Sway VS Code extension itself.",
78 | "type": "boolean",
79 | "default": false
80 | },
81 | "sway-lsp.debug.showCollectedTokensAsWarnings": {
82 | "scope": "window",
83 | "type": "string",
84 | "description": "Show either successfully parsed or typed tokens by the sway-lsp server as warnings. If set to off, sway-lsp will revert to only showing warnings and errors reported by the compiler.",
85 | "enum": [
86 | "off",
87 | "parsed",
88 | "typed"
89 | ],
90 | "enumDescriptions": [
91 | "Debugging off",
92 | "Show parsed tokens",
93 | "Show typed tokens"
94 | ],
95 | "default": "off"
96 | },
97 | "sway-lsp.diagnostic.showWarnings": {
98 | "description": "Show compiler warnings",
99 | "type": "boolean",
100 | "default": true
101 | },
102 | "sway-lsp.diagnostic.showErrors": {
103 | "description": "Show compiler errors",
104 | "type": "boolean",
105 | "default": true
106 | },
107 | "sway-lsp.diagnostic.binPath": {
108 | "description": "Optionally override the path to the Sway language server executable. If empty, the extension will use the forc-lsp executable to which your $PATH resolves (recommended for most users).",
109 | "type": "string",
110 | "default": "",
111 | "pattern": "(^/(.+/)*forc-lsp$)|^$",
112 | "patternErrorMessage": "Must be an absolute path to the `forc-lsp` executable, or left empty."
113 | },
114 | "sway-lsp.diagnostic.disableLsp": {
115 | "description": "Disable the LSP server. This will disable all language features except for basic syntax highlighting.",
116 | "type": "boolean",
117 | "default": false
118 | },
119 | "sway-lsp.logging.level": {
120 | "scope": "window",
121 | "type": "string",
122 | "description": "Set the log level for LSP server logs.",
123 | "enum": [
124 | "off",
125 | "error",
126 | "warn",
127 | "info",
128 | "debug",
129 | "trace"
130 | ],
131 | "default": "error"
132 | },
133 | "sway-lsp.inlayHints.renderColons": {
134 | "markdownDescription": "Whether to render leading colons for type hints, and trailing colons for parameter hints.",
135 | "default": true,
136 | "type": "boolean"
137 | },
138 | "sway-lsp.inlayHints.typeHints": {
139 | "markdownDescription": "Whether to show inlay type hints for variables.",
140 | "default": true,
141 | "type": "boolean"
142 | },
143 | "sway-lsp.inlayHints.maxLength": {
144 | "markdownDescription": "Maximum length for inlay hints. Set to null to have an unlimited length.",
145 | "default": 25,
146 | "type": [
147 | "null",
148 | "integer"
149 | ],
150 | "minimum": 0
151 | },
152 | "sway-lsp.onEnter.continueDocComments": {
153 | "markdownDescription": "Whether to continue /// comments when enter is pressed.",
154 | "default": false,
155 | "type": "boolean"
156 | },
157 | "sway-lsp.onEnter.continueComments": {
158 | "markdownDescription": "Whether to continue // comments when enter is pressed.",
159 | "default": false,
160 | "type": "boolean"
161 | }
162 | },
163 | "commands": [
164 | {
165 | "command": "sway.runScript",
166 | "title": "Sway: Run script"
167 | },
168 | {
169 | "command": "sway.runTests",
170 | "title": "Sway: Run tests"
171 | },
172 | {
173 | "command": "sway.forcBuild",
174 | "title": "Sway: Build"
175 | },
176 | {
177 | "command": "sway.startFuelCore",
178 | "title": "Sway: Start Fuel Core"
179 | },
180 | {
181 | "command": "sway.stopFuelCore",
182 | "title": "Sway: Stop Fuel Core"
183 | },
184 | {
185 | "command": "sway.showLexedAst",
186 | "title": "Sway: Show Lexed AST"
187 | },
188 | {
189 | "command": "sway.showParsedAst",
190 | "title": "Sway: Show Parsed AST"
191 | },
192 | {
193 | "command": "sway.showTypedAst",
194 | "title": "Sway: Show Typed AST"
195 | },
196 | {
197 | "command": "sway.viewBuildPlan",
198 | "title": "Sway: View Build Plan"
199 | },
200 | {
201 | "command": "sway.installServer",
202 | "title": "Sway: Install Server"
203 | },
204 | {
205 | "command": "sway.goToLocation",
206 | "title": "Sway: Go To Definition"
207 | },
208 | {
209 | "command": "sway.peekLocations",
210 | "title": "Sway: Peek Locations"
211 | }
212 | ]
213 | },
214 | "languages": [
215 | {
216 | "id": "sway",
217 | "aliases": [
218 | "Sway",
219 | "sway"
220 | ],
221 | "extensions": [
222 | ".sw"
223 | ],
224 | "configuration": "./language-configuration.json"
225 | }
226 | ],
227 | "commands": [
228 | {
229 | "command": "programs.refreshEntry",
230 | "title": "Refresh",
231 | "icon": {
232 | "light": "images/light/refresh.svg",
233 | "dark": "images/dark/refresh.svg"
234 | }
235 | },
236 | {
237 | "command": "programs.editEntry",
238 | "title": "Edit",
239 | "icon": {
240 | "light": "images/light/edit.svg",
241 | "dark": "images/dark/edit.svg"
242 | }
243 | },
244 | {
245 | "command": "programs.run",
246 | "title": "Run",
247 | "icon": {
248 | "light": "images/light/play.svg",
249 | "dark": "images/dark/play.svg"
250 | }
251 | },
252 | {
253 | "command": "sway.runScript",
254 | "title": "Sway: Run script"
255 | },
256 | {
257 | "command": "sway.runTests",
258 | "title": "Sway: Run tests"
259 | },
260 | {
261 | "command": "sway.forcBuild",
262 | "title": "Sway: Build"
263 | },
264 | {
265 | "command": "sway.startFuelCore",
266 | "title": "Sway: Start Fuel Core"
267 | },
268 | {
269 | "command": "sway.stopFuelCore",
270 | "title": "Sway: Stop Fuel Core"
271 | },
272 | {
273 | "command": "sway.showLexedAst",
274 | "title": "Sway: Show Lexed AST"
275 | },
276 | {
277 | "command": "sway.showParsedAst",
278 | "title": "Sway: Show Parsed AST"
279 | },
280 | {
281 | "command": "sway.showTypedAst",
282 | "title": "Sway: Show Typed AST"
283 | },
284 | {
285 | "command": "sway.viewBuildPlan",
286 | "title": "Sway: View Build Plan"
287 | },
288 | {
289 | "command": "sway.installServer",
290 | "title": "Sway: Install Server"
291 | },
292 | {
293 | "command": "sway.goToLocation",
294 | "title": "Sway: Go To Definition",
295 | "args": [
296 | {
297 | "name": "uri",
298 | "description": "URI of the document to open.",
299 | "schema": {
300 | "type": "string"
301 | }
302 | },
303 | {
304 | "name": "range",
305 | "description": "Range of selected text in the document.",
306 | "schema": {
307 | "$ref": "#/definitions/Range"
308 | }
309 | }
310 | ]
311 | },
312 | {
313 | "command": "sway.peekLocations",
314 | "title": "Sway: Peek Locations",
315 | "args": [
316 | {
317 | "name": "locations",
318 | "description": "Array of locations.",
319 | "schema": {
320 | "type": "array",
321 | "items": [
322 | {
323 | "$ref": "#/definitions/Location"
324 | }
325 | ]
326 | }
327 | }
328 | ]
329 | }
330 | ],
331 | "snippets": [
332 | {
333 | "language": "sway",
334 | "path": "./snippets/sway.json"
335 | }
336 | ],
337 | "grammars": [
338 | {
339 | "language": "sway",
340 | "scopeName": "source.sway",
341 | "path": "./syntaxes/sway.tmLanguage.json"
342 | }
343 | ],
344 | "breakpoints": [
345 | {
346 | "language": "sway"
347 | }
348 | ],
349 | "debuggers": [
350 | {
351 | "type": "sway",
352 | "label": "Sway Debugger",
353 | "program": "/usr/bin/env",
354 | "args": [
355 | "forc-debug",
356 | "--serve"
357 | ],
358 | "languages": [
359 | "sway"
360 | ],
361 | "configurationAttributes": {
362 | "launch": {
363 | "required": [
364 | "program"
365 | ],
366 | "properties": {
367 | "program": {
368 | "type": "string",
369 | "description": "Absolute path to a text file.",
370 | "default": "${file}"
371 | }
372 | }
373 | },
374 | "attach": {
375 | "required": [
376 | "program"
377 | ],
378 | "properties": {
379 | "program": {
380 | "type": "string",
381 | "description": "Absolute path to a text file.",
382 | "default": "${file}"
383 | }
384 | }
385 | }
386 | }
387 | }
388 | ]
389 | },
390 | "dependencies": {
391 | "@hpcc-js/wasm": "^2.13.0",
392 | "child_process": "^1.0.2",
393 | "d3": "^7.8.5",
394 | "d3-graphviz": "^5.0.2",
395 | "semver": "^7.6.2",
396 | "util": "^0.12.5",
397 | "vscode-languageclient": "^8.0.0-next.14"
398 | },
399 | "devDependencies": {
400 | "@types/node": "^12.20.46",
401 | "@types/vscode": "^1.66.0",
402 | "@typescript-eslint/eslint-plugin": "^4.33.0",
403 | "@typescript-eslint/parser": "^4.33.0",
404 | "@vscode/test-electron": "^1.6.1",
405 | "esbuild": "^0.20.1",
406 | "eslint": "^7.32.0",
407 | "prettier": "^2.5.1",
408 | "prettier-plugin-organize-imports": "^3.2.2",
409 | "typescript": "^4.5.5",
410 | "vsce": "^2.5.3",
411 | "vscode-tmgrammar-test": "^0.1.1"
412 | }
413 | }
414 |
--------------------------------------------------------------------------------
/client/test/syntaxes/particle.sw.snap:
--------------------------------------------------------------------------------
1 | >script;
2 | #^^^^^^ source.sway source.sway meta.attribute.sway
3 | # ^ source.sway
4 | >
5 | >/// A simple Particle struct
6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.sway comment.line.documentation.sway
7 | >pub struct Particle {
8 | #^^^ source.sway keyword.other.sway
9 | # ^ source.sway
10 | # ^^^^^^ source.sway keyword.declaration.struct.sway
11 | # ^ source.sway
12 | # ^^^^^^^^ source.sway entity.name.type.struct.sway
13 | # ^ source.sway
14 | # ^ source.sway punctuation.brackets.curly.sway
15 | > position: [u64; 3],
16 | #^^^^ source.sway
17 | # ^^^^^^^^ source.sway variable.other.sway
18 | # ^ source.sway keyword.operator.key-value.sway
19 | # ^ source.sway
20 | # ^ source.sway punctuation.brackets.square.sway
21 | # ^^^ source.sway entity.name.type.numeric.sway
22 | # ^ source.sway punctuation.semi.sway
23 | # ^ source.sway
24 | # ^ source.sway constant.numeric.decimal.sway
25 | # ^ source.sway punctuation.brackets.square.sway
26 | # ^ source.sway punctuation.comma.sway
27 | > velocity: [u64; 3],
28 | #^^^^ source.sway
29 | # ^^^^^^^^ source.sway variable.other.sway
30 | # ^ source.sway keyword.operator.key-value.sway
31 | # ^ source.sway
32 | # ^ source.sway punctuation.brackets.square.sway
33 | # ^^^ source.sway entity.name.type.numeric.sway
34 | # ^ source.sway punctuation.semi.sway
35 | # ^ source.sway
36 | # ^ source.sway constant.numeric.decimal.sway
37 | # ^ source.sway punctuation.brackets.square.sway
38 | # ^ source.sway punctuation.comma.sway
39 | > acceleration: [u64; 3],
40 | #^^^^ source.sway
41 | # ^^^^^^^^^^^^ source.sway variable.other.sway
42 | # ^ source.sway keyword.operator.key-value.sway
43 | # ^ source.sway
44 | # ^ source.sway punctuation.brackets.square.sway
45 | # ^^^ source.sway entity.name.type.numeric.sway
46 | # ^ source.sway punctuation.semi.sway
47 | # ^ source.sway
48 | # ^ source.sway constant.numeric.decimal.sway
49 | # ^ source.sway punctuation.brackets.square.sway
50 | # ^ source.sway punctuation.comma.sway
51 | > mass: u64,
52 | #^^^^ source.sway
53 | # ^^^^ source.sway variable.other.sway
54 | # ^ source.sway keyword.operator.key-value.sway
55 | # ^ source.sway
56 | # ^^^ source.sway entity.name.type.numeric.sway
57 | # ^ source.sway punctuation.comma.sway
58 | >}
59 | #^ source.sway punctuation.brackets.curly.sway
60 | >
61 | >impl Particle {
62 | #^^^^ source.sway keyword.other.sway
63 | # ^ source.sway
64 | # ^^^^^^^^ source.sway entity.name.type.sway
65 | # ^ source.sway
66 | # ^ source.sway punctuation.brackets.curly.sway
67 | > /// Creates a new Particle with the given position, velocity, acceleration, and mass
68 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.sway comment.line.documentation.sway
69 | > fn new(position: [u64; 3], velocity: [u64; 3], acceleration: [u64; 3], mass: u64) -> Particle {
70 | #^^^^ source.sway
71 | # ^^ source.sway meta.function.definition.sway keyword.other.fn.sway
72 | # ^ source.sway meta.function.definition.sway
73 | # ^^^ source.sway meta.function.definition.sway entity.name.function.sway
74 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
75 | # ^^^^^^^^ source.sway meta.function.definition.sway variable.other.sway
76 | # ^ source.sway meta.function.definition.sway keyword.operator.key-value.sway
77 | # ^ source.sway meta.function.definition.sway
78 | # ^ source.sway meta.function.definition.sway punctuation.brackets.square.sway
79 | # ^^^ source.sway meta.function.definition.sway entity.name.type.numeric.sway
80 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
81 | # ^ source.sway
82 | # ^ source.sway constant.numeric.decimal.sway
83 | # ^ source.sway punctuation.brackets.square.sway
84 | # ^ source.sway punctuation.comma.sway
85 | # ^ source.sway
86 | # ^^^^^^^^ source.sway variable.other.sway
87 | # ^ source.sway keyword.operator.key-value.sway
88 | # ^ source.sway
89 | # ^ source.sway punctuation.brackets.square.sway
90 | # ^^^ source.sway entity.name.type.numeric.sway
91 | # ^ source.sway punctuation.semi.sway
92 | # ^ source.sway
93 | # ^ source.sway constant.numeric.decimal.sway
94 | # ^ source.sway punctuation.brackets.square.sway
95 | # ^ source.sway punctuation.comma.sway
96 | # ^ source.sway
97 | # ^^^^^^^^^^^^ source.sway variable.other.sway
98 | # ^ source.sway keyword.operator.key-value.sway
99 | # ^ source.sway
100 | # ^ source.sway punctuation.brackets.square.sway
101 | # ^^^ source.sway entity.name.type.numeric.sway
102 | # ^ source.sway punctuation.semi.sway
103 | # ^ source.sway
104 | # ^ source.sway constant.numeric.decimal.sway
105 | # ^ source.sway punctuation.brackets.square.sway
106 | # ^ source.sway punctuation.comma.sway
107 | # ^ source.sway
108 | # ^^^^ source.sway variable.other.sway
109 | # ^ source.sway keyword.operator.key-value.sway
110 | # ^ source.sway
111 | # ^^^ source.sway entity.name.type.numeric.sway
112 | # ^ source.sway punctuation.brackets.round.sway
113 | # ^ source.sway
114 | # ^^ source.sway keyword.operator.arrow.skinny.sway
115 | # ^ source.sway
116 | # ^^^^^^^^ source.sway entity.name.type.sway
117 | # ^ source.sway
118 | # ^ source.sway punctuation.brackets.curly.sway
119 | > Particle {
120 | #^^^^^^^^ source.sway
121 | # ^^^^^^^^ source.sway entity.name.type.sway
122 | # ^ source.sway
123 | # ^ source.sway punctuation.brackets.curly.sway
124 | > position: position,
125 | #^^^^^^^^^^^^ source.sway
126 | # ^^^^^^^^ source.sway variable.other.sway
127 | # ^ source.sway keyword.operator.key-value.sway
128 | # ^ source.sway
129 | # ^^^^^^^^ source.sway variable.other.sway
130 | # ^ source.sway punctuation.comma.sway
131 | > velocity: velocity,
132 | #^^^^^^^^^^^^ source.sway
133 | # ^^^^^^^^ source.sway variable.other.sway
134 | # ^ source.sway keyword.operator.key-value.sway
135 | # ^ source.sway
136 | # ^^^^^^^^ source.sway variable.other.sway
137 | # ^ source.sway punctuation.comma.sway
138 | > acceleration: acceleration,
139 | #^^^^^^^^^^^^ source.sway
140 | # ^^^^^^^^^^^^ source.sway variable.other.sway
141 | # ^ source.sway keyword.operator.key-value.sway
142 | # ^ source.sway
143 | # ^^^^^^^^^^^^ source.sway variable.other.sway
144 | # ^ source.sway punctuation.comma.sway
145 | > mass: mass,
146 | #^^^^^^^^^^^^ source.sway
147 | # ^^^^ source.sway variable.other.sway
148 | # ^ source.sway keyword.operator.key-value.sway
149 | # ^ source.sway
150 | # ^^^^ source.sway variable.other.sway
151 | # ^ source.sway punctuation.comma.sway
152 | > }
153 | #^^^^^^^^ source.sway
154 | # ^ source.sway punctuation.brackets.curly.sway
155 | > }
156 | #^^^^ source.sway
157 | # ^ source.sway punctuation.brackets.curly.sway
158 | >}
159 | #^ source.sway punctuation.brackets.curly.sway
160 | >
161 | >fn main() {
162 | #^^ source.sway meta.function.definition.sway keyword.other.fn.sway
163 | # ^ source.sway meta.function.definition.sway
164 | # ^^^^ source.sway meta.function.definition.sway entity.name.function.sway
165 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
166 | # ^ source.sway meta.function.definition.sway punctuation.brackets.round.sway
167 | # ^ source.sway meta.function.definition.sway
168 | # ^ source.sway meta.function.definition.sway punctuation.brackets.curly.sway
169 | > let position = [0, 0, 0];
170 | #^^^^ source.sway
171 | # ^^^ source.sway storage.modifier.sway
172 | # ^ source.sway
173 | # ^^^^^^^^ source.sway variable.other.sway
174 | # ^ source.sway
175 | # ^ source.sway keyword.operator.assignment.equal.sway
176 | # ^ source.sway
177 | # ^ source.sway punctuation.brackets.square.sway
178 | # ^ source.sway constant.numeric.decimal.sway
179 | # ^ source.sway punctuation.comma.sway
180 | # ^ source.sway
181 | # ^ source.sway constant.numeric.decimal.sway
182 | # ^ source.sway punctuation.comma.sway
183 | # ^ source.sway
184 | # ^ source.sway constant.numeric.decimal.sway
185 | # ^ source.sway punctuation.brackets.square.sway
186 | # ^ source.sway punctuation.semi.sway
187 | > let velocity = [0, 1, 0];
188 | #^^^^ source.sway
189 | # ^^^ source.sway storage.modifier.sway
190 | # ^ source.sway
191 | # ^^^^^^^^ source.sway variable.other.sway
192 | # ^ source.sway
193 | # ^ source.sway keyword.operator.assignment.equal.sway
194 | # ^ source.sway
195 | # ^ source.sway punctuation.brackets.square.sway
196 | # ^ source.sway constant.numeric.decimal.sway
197 | # ^ source.sway punctuation.comma.sway
198 | # ^ source.sway
199 | # ^ source.sway constant.numeric.decimal.sway
200 | # ^ source.sway punctuation.comma.sway
201 | # ^ source.sway
202 | # ^ source.sway constant.numeric.decimal.sway
203 | # ^ source.sway punctuation.brackets.square.sway
204 | # ^ source.sway punctuation.semi.sway
205 | > let acceleration = [1, 1, position[1]];
206 | #^^^^ source.sway
207 | # ^^^ source.sway storage.modifier.sway
208 | # ^ source.sway
209 | # ^^^^^^^^^^^^ source.sway variable.other.sway
210 | # ^ source.sway
211 | # ^ source.sway keyword.operator.assignment.equal.sway
212 | # ^ source.sway
213 | # ^ source.sway punctuation.brackets.square.sway
214 | # ^ source.sway constant.numeric.decimal.sway
215 | # ^ source.sway punctuation.comma.sway
216 | # ^ source.sway
217 | # ^ source.sway constant.numeric.decimal.sway
218 | # ^ source.sway punctuation.comma.sway
219 | # ^ source.sway
220 | # ^^^^^^^^ source.sway variable.other.sway
221 | # ^ source.sway punctuation.brackets.square.sway
222 | # ^ source.sway constant.numeric.decimal.sway
223 | # ^ source.sway punctuation.brackets.square.sway
224 | # ^ source.sway punctuation.brackets.square.sway
225 | # ^ source.sway punctuation.semi.sway
226 | > let mass = 10;
227 | #^^^^ source.sway
228 | # ^^^ source.sway storage.modifier.sway
229 | # ^ source.sway
230 | # ^^^^ source.sway variable.other.sway
231 | # ^ source.sway
232 | # ^ source.sway keyword.operator.assignment.equal.sway
233 | # ^ source.sway
234 | # ^^ source.sway constant.numeric.decimal.sway
235 | # ^ source.sway punctuation.semi.sway
236 | > let p = ~Particle::new(position, velocity, acceleration, mass);
237 | #^^^^ source.sway
238 | # ^^^ source.sway storage.modifier.sway
239 | # ^ source.sway
240 | # ^ source.sway variable.other.sway
241 | # ^ source.sway
242 | # ^ source.sway keyword.operator.assignment.equal.sway
243 | # ^^ source.sway
244 | # ^^^^^^^^ source.sway entity.name.type.sway
245 | # ^^ source.sway keyword.operator.namespace.sway
246 | # ^^^ source.sway meta.function.call.sway entity.name.function.sway
247 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
248 | # ^^^^^^^^ source.sway meta.function.call.sway variable.other.sway
249 | # ^ source.sway meta.function.call.sway punctuation.comma.sway
250 | # ^ source.sway meta.function.call.sway
251 | # ^^^^^^^^ source.sway meta.function.call.sway variable.other.sway
252 | # ^ source.sway meta.function.call.sway punctuation.comma.sway
253 | # ^ source.sway meta.function.call.sway
254 | # ^^^^^^^^^^^^ source.sway meta.function.call.sway variable.other.sway
255 | # ^ source.sway meta.function.call.sway punctuation.comma.sway
256 | # ^ source.sway meta.function.call.sway
257 | # ^^^^ source.sway meta.function.call.sway variable.other.sway
258 | # ^ source.sway meta.function.call.sway punctuation.brackets.round.sway
259 | # ^ source.sway punctuation.semi.sway
260 | >}
261 | #^ source.sway punctuation.brackets.curly.sway
262 | >
--------------------------------------------------------------------------------
/syntaxes/sway.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Sway",
3 | "fileTypes": ["sw"],
4 | "scopeName": "source.sway",
5 | "patterns": [
6 | {
7 | "comment": "boxed slice literal",
8 | "begin": "(<)(\\[)",
9 | "beginCaptures": {
10 | "1": {
11 | "name": "punctuation.brackets.angle.sway"
12 | },
13 | "2": {
14 | "name": "punctuation.brackets.square.sway"
15 | }
16 | },
17 | "end": ">",
18 | "endCaptures": {
19 | "0": {
20 | "name": "punctuation.brackets.angle.sway"
21 | }
22 | },
23 | "patterns": [
24 | {
25 | "include": "#block-comments"
26 | },
27 | {
28 | "include": "#comments"
29 | },
30 | {
31 | "include": "#gtypes"
32 | },
33 | {
34 | "include": "#lvariables"
35 | },
36 | {
37 | "include": "#lifetimes"
38 | },
39 | {
40 | "include": "#punctuation"
41 | },
42 | {
43 | "include": "#types"
44 | }
45 | ]
46 | },
47 | {
48 | "comment": "attributes",
49 | "name": "meta.attribute.sway",
50 | "begin": "(#)(\\!?)(\\[)",
51 | "beginCaptures": {
52 | "1": {
53 | "name": "punctuation.definition.attribute.sway"
54 | },
55 | "2": {
56 | "name": "keyword.operator.attribute.inner.sway"
57 | },
58 | "3": {
59 | "name": "punctuation.brackets.attribute.sway"
60 | }
61 | },
62 | "end": "\\]",
63 | "endCaptures": {
64 | "0": {
65 | "name": "punctuation.brackets.attribute.sway"
66 | }
67 | },
68 | "patterns": [
69 | {
70 | "include": "#block-comments"
71 | },
72 | {
73 | "include": "#comments"
74 | },
75 | {
76 | "include": "#keywords"
77 | },
78 | {
79 | "include": "#lifetimes"
80 | },
81 | {
82 | "include": "#punctuation"
83 | },
84 | {
85 | "include": "#strings"
86 | },
87 | {
88 | "include": "#gtypes"
89 | },
90 | {
91 | "include": "#types"
92 | }
93 | ]
94 | },
95 | {
96 | "comment": "dependency",
97 | "match": "(dep)\\s+((?:r#(?!crate|[Ss]elf|super))?[a-z][A-Za-z0-9_]*)",
98 | "captures": {
99 | "1": {
100 | "name": "storage.type.sway"
101 | },
102 | "2": {
103 | "name": "entity.name.dependency.sway"
104 | }
105 | }
106 | },
107 | {
108 | "comment": "external crate imports",
109 | "name": "meta.import.sway",
110 | "begin": "\\b(extern)\\s+(crate)",
111 | "beginCaptures": {
112 | "1": {
113 | "name": "storage.type.sway"
114 | },
115 | "2": {
116 | "name": "keyword.other.crate.sway"
117 | }
118 | },
119 | "end": ";",
120 | "endCaptures": {
121 | "0": {
122 | "name": "punctuation.semi.sway"
123 | }
124 | },
125 | "patterns": [
126 | {
127 | "include": "#block-comments"
128 | },
129 | {
130 | "include": "#comments"
131 | },
132 | {
133 | "include": "#keywords"
134 | },
135 | {
136 | "include": "#punctuation"
137 | }
138 | ]
139 | },
140 | {
141 | "comment": "use statements",
142 | "name": "meta.use.sway",
143 | "begin": "\\b(use)\\s",
144 | "beginCaptures": {
145 | "1": {
146 | "name": "keyword.other.sway"
147 | }
148 | },
149 | "end": ";",
150 | "endCaptures": {
151 | "0": {
152 | "name": "punctuation.semi.sway"
153 | }
154 | },
155 | "patterns": [
156 | {
157 | "include": "#block-comments"
158 | },
159 | {
160 | "include": "#comments"
161 | },
162 | {
163 | "include": "#keywords"
164 | },
165 | {
166 | "include": "#namespaces"
167 | },
168 | {
169 | "include": "#punctuation"
170 | },
171 | {
172 | "include": "#types"
173 | },
174 | {
175 | "include": "#lvariables"
176 | }
177 | ]
178 | },
179 | {
180 | "include": "#block-comments"
181 | },
182 | {
183 | "include": "#comments"
184 | },
185 | {
186 | "include": "#lvariables"
187 | },
188 | {
189 | "include": "#constants"
190 | },
191 | {
192 | "include": "#gtypes"
193 | },
194 | {
195 | "include": "#functions"
196 | },
197 | {
198 | "include": "#types"
199 | },
200 | {
201 | "include": "#keywords"
202 | },
203 | {
204 | "include": "#lifetimes"
205 | },
206 | {
207 | "include": "#macros"
208 | },
209 | {
210 | "include": "#namespaces"
211 | },
212 | {
213 | "include": "#punctuation"
214 | },
215 | {
216 | "include": "#strings"
217 | },
218 | {
219 | "include": "#variables"
220 | }
221 | ],
222 | "repository": {
223 | "comments": {
224 | "patterns": [
225 | {
226 | "comment": "documentation comments",
227 | "name": "comment.line.documentation.sway",
228 | "match": "^\\s*///.*"
229 | },
230 | {
231 | "comment": "line comments",
232 | "name": "comment.line.double-slash.sway",
233 | "match": "\\s*//.*"
234 | }
235 | ]
236 | },
237 | "block-comments": {
238 | "patterns": [
239 | {
240 | "comment": "empty block comments",
241 | "name": "comment.block.sway",
242 | "match": "/\\*\\*/"
243 | },
244 | {
245 | "comment": "block documentation comments",
246 | "name": "comment.block.documentation.sway",
247 | "begin": "/\\*\\*",
248 | "end": "\\*/",
249 | "patterns": [
250 | {
251 | "include": "#block-comments"
252 | }
253 | ]
254 | },
255 | {
256 | "comment": "block comments",
257 | "name": "comment.block.sway",
258 | "begin": "/\\*(?!\\*)",
259 | "end": "\\*/",
260 | "patterns": [
261 | {
262 | "include": "#block-comments"
263 | }
264 | ]
265 | }
266 | ]
267 | },
268 | "constants": {
269 | "patterns": [
270 | {
271 | "comment": "ALL CAPS constants",
272 | "name": "constant.other.caps.sway",
273 | "match": "\\b[A-Z]{2}[A-Z0-9_]*\\b"
274 | },
275 | {
276 | "comment": "constant declarations",
277 | "match": "\\b(const)\\s+([A-Z][A-Za-z0-9_]*)\\b",
278 | "captures": {
279 | "1": {
280 | "name": "storage.type.sway"
281 | },
282 | "2": {
283 | "name": "constant.other.caps.sway"
284 | }
285 | }
286 | },
287 | {
288 | "comment": "decimal integers and floats",
289 | "name": "constant.numeric.decimal.sway",
290 | "match": "\\b\\d[\\d_]*(\\.?)[\\d_]*(?:(E)([+-])([\\d_]+))?(f32|f64|i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
291 | "captures": {
292 | "1": {
293 | "name": "punctuation.separator.dot.decimal.sway"
294 | },
295 | "2": {
296 | "name": "keyword.operator.exponent.sway"
297 | },
298 | "3": {
299 | "name": "keyword.operator.exponent.sign.sway"
300 | },
301 | "4": {
302 | "name": "constant.numeric.decimal.exponent.mantissa.sway"
303 | },
304 | "5": {
305 | "name": "entity.name.type.numeric.sway"
306 | }
307 | }
308 | },
309 | {
310 | "comment": "hexadecimal integers",
311 | "name": "constant.numeric.hex.sway",
312 | "match": "\\b0x[\\da-fA-F_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
313 | "captures": {
314 | "1": {
315 | "name": "entity.name.type.numeric.sway"
316 | }
317 | }
318 | },
319 | {
320 | "comment": "octal integers",
321 | "name": "constant.numeric.oct.sway",
322 | "match": "\\b0o[0-7_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
323 | "captures": {
324 | "1": {
325 | "name": "entity.name.type.numeric.sway"
326 | }
327 | }
328 | },
329 | {
330 | "comment": "binary integers",
331 | "name": "constant.numeric.bin.sway",
332 | "match": "\\b0b[01_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
333 | "captures": {
334 | "1": {
335 | "name": "entity.name.type.numeric.sway"
336 | }
337 | }
338 | },
339 | {
340 | "comment": "booleans",
341 | "name": "constant.language.bool.sway",
342 | "match": "\\b(true|false)\\b"
343 | }
344 | ]
345 | },
346 | "escapes": {
347 | "comment": "escapes: ASCII, byte, Unicode, quote, regex",
348 | "name": "constant.character.escape.sway",
349 | "match": "(\\\\)(?:(?:(x[0-7][0-7a-fA-F])|(u(\\{)[\\da-fA-F]{4,6}(\\}))|.))",
350 | "captures": {
351 | "1": {
352 | "name": "constant.character.escape.backslash.sway"
353 | },
354 | "2": {
355 | "name": "constant.character.escape.bit.sway"
356 | },
357 | "3": {
358 | "name": "constant.character.escape.unicode.sway"
359 | },
360 | "4": {
361 | "name": "constant.character.escape.unicode.punctuation.sway"
362 | },
363 | "5": {
364 | "name": "constant.character.escape.unicode.punctuation.sway"
365 | }
366 | }
367 | },
368 | "functions": {
369 | "patterns": [
370 | {
371 | "comment": "pub as a function",
372 | "match": "\\b(pub)(\\()",
373 | "captures": {
374 | "1": {
375 | "name": "keyword.other.sway"
376 | },
377 | "2": {
378 | "name": "punctuation.brackets.round.sway"
379 | }
380 | }
381 | },
382 | {
383 | "comment": "assembly block",
384 | "name": "meta.asm.definition.sway",
385 | "begin": "\\b(asm)((\\())",
386 | "beginCaptures": {
387 | "1": {
388 | "name": "meta.attribute.asm.sway"
389 | },
390 | "2": {
391 | "name": "punctuation.brackets.round.sway"
392 | }
393 | },
394 | "end": "\\{|;",
395 | "endCaptures": {
396 | "0": {
397 | "name": "punctuation.brackets.curly.sway"
398 | }
399 | },
400 | "patterns": [
401 | {
402 | "include": "#block-comments"
403 | },
404 | {
405 | "include": "#comments"
406 | },
407 | {
408 | "include": "#keywords"
409 | },
410 | {
411 | "include": "#lvariables"
412 | },
413 | {
414 | "include": "#constants"
415 | },
416 | {
417 | "include": "#gtypes"
418 | },
419 | {
420 | "include": "#functions"
421 | },
422 | {
423 | "include": "#lifetimes"
424 | },
425 | {
426 | "include": "#macros"
427 | },
428 | {
429 | "include": "#namespaces"
430 | },
431 | {
432 | "include": "#punctuation"
433 | },
434 | {
435 | "include": "#strings"
436 | },
437 | {
438 | "include": "#types"
439 | },
440 | {
441 | "include": "#variables"
442 | }
443 | ]
444 | },
445 | {
446 | "comment": "function definition",
447 | "name": "meta.function.definition.sway",
448 | "begin": "\\b(fn)\\s+((?:r#(?!crate|[Ss]elf|super))?[A-Za-z0-9_]+)((\\()|(<))",
449 | "beginCaptures": {
450 | "1": {
451 | "name": "keyword.other.fn.sway"
452 | },
453 | "2": {
454 | "name": "entity.name.function.sway"
455 | },
456 | "4": {
457 | "name": "punctuation.brackets.round.sway"
458 | },
459 | "5": {
460 | "name": "punctuation.brackets.angle.sway"
461 | }
462 | },
463 | "end": "\\{|;",
464 | "endCaptures": {
465 | "0": {
466 | "name": "punctuation.brackets.curly.sway"
467 | }
468 | },
469 | "patterns": [
470 | {
471 | "include": "#block-comments"
472 | },
473 | {
474 | "include": "#comments"
475 | },
476 | {
477 | "include": "#keywords"
478 | },
479 | {
480 | "include": "#lvariables"
481 | },
482 | {
483 | "include": "#constants"
484 | },
485 | {
486 | "include": "#gtypes"
487 | },
488 | {
489 | "include": "#functions"
490 | },
491 | {
492 | "include": "#lifetimes"
493 | },
494 | {
495 | "include": "#macros"
496 | },
497 | {
498 | "include": "#namespaces"
499 | },
500 | {
501 | "include": "#punctuation"
502 | },
503 | {
504 | "include": "#strings"
505 | },
506 | {
507 | "include": "#types"
508 | },
509 | {
510 | "include": "#variables"
511 | }
512 | ]
513 | },
514 | {
515 | "comment": "function/method calls, chaining",
516 | "name": "meta.function.call.sway",
517 | "begin": "((?:r#(?!crate|[Ss]elf|super))?[A-Za-z0-9_]+)(\\()",
518 | "beginCaptures": {
519 | "1": {
520 | "name": "entity.name.function.sway"
521 | },
522 | "2": {
523 | "name": "punctuation.brackets.round.sway"
524 | }
525 | },
526 | "end": "\\)",
527 | "endCaptures": {
528 | "0": {
529 | "name": "punctuation.brackets.round.sway"
530 | }
531 | },
532 | "patterns": [
533 | {
534 | "include": "#block-comments"
535 | },
536 | {
537 | "include": "#comments"
538 | },
539 | {
540 | "include": "#keywords"
541 | },
542 | {
543 | "include": "#lvariables"
544 | },
545 | {
546 | "include": "#constants"
547 | },
548 | {
549 | "include": "#gtypes"
550 | },
551 | {
552 | "include": "#functions"
553 | },
554 | {
555 | "include": "#lifetimes"
556 | },
557 | {
558 | "include": "#macros"
559 | },
560 | {
561 | "include": "#namespaces"
562 | },
563 | {
564 | "include": "#punctuation"
565 | },
566 | {
567 | "include": "#strings"
568 | },
569 | {
570 | "include": "#types"
571 | },
572 | {
573 | "include": "#variables"
574 | }
575 | ]
576 | },
577 | {
578 | "comment": "function/method calls with turbofish",
579 | "name": "meta.function.call.sway",
580 | "begin": "((?:r#(?!crate|[Ss]elf|super))?[A-Za-z0-9_]+)(?=::<.*>\\()",
581 | "beginCaptures": {
582 | "1": {
583 | "name": "entity.name.function.sway"
584 | }
585 | },
586 | "end": "\\)",
587 | "endCaptures": {
588 | "0": {
589 | "name": "punctuation.brackets.round.sway"
590 | }
591 | },
592 | "patterns": [
593 | {
594 | "include": "#block-comments"
595 | },
596 | {
597 | "include": "#comments"
598 | },
599 | {
600 | "include": "#keywords"
601 | },
602 | {
603 | "include": "#lvariables"
604 | },
605 | {
606 | "include": "#constants"
607 | },
608 | {
609 | "include": "#gtypes"
610 | },
611 | {
612 | "include": "#functions"
613 | },
614 | {
615 | "include": "#lifetimes"
616 | },
617 | {
618 | "include": "#macros"
619 | },
620 | {
621 | "include": "#namespaces"
622 | },
623 | {
624 | "include": "#punctuation"
625 | },
626 | {
627 | "include": "#strings"
628 | },
629 | {
630 | "include": "#types"
631 | },
632 | {
633 | "include": "#variables"
634 | }
635 | ]
636 | }
637 | ]
638 | },
639 | "keywords": {
640 | "patterns": [
641 | {
642 | "comment": "control flow keywords",
643 | "name": "keyword.control.sway",
644 | "match": "\\b(await|break|continue|do|else|for|if|loop|match|return|try|while|yield)\\b"
645 | },
646 | {
647 | "comment": "storage keywords",
648 | "name": "keyword.other.sway storage.type.sway",
649 | "match": "\\b(extern|macro|dep)\\b"
650 | },
651 | {
652 | "comment": "const keyword",
653 | "name": "storage.modifier.sway",
654 | "match": "\\b(const)\\b"
655 | },
656 | {
657 | "comment": "let keyword",
658 | "name": "storage.modifier.sway",
659 | "match": "\\b(let)\\b"
660 | },
661 | {
662 | "comment": "type keyword",
663 | "name": "keyword.declaration.type.sway",
664 | "match": "\\b(type)\\b"
665 | },
666 | {
667 | "comment": "enum keyword",
668 | "name": "keyword.declaration.enum.sway",
669 | "match": "\\b(enum)\\b"
670 | },
671 | {
672 | "comment": "trait keyword",
673 | "name": "keyword.declaration.trait.sway",
674 | "match": "\\b(trait)\\b"
675 | },
676 | {
677 | "comment": "abi keyword",
678 | "name": "keyword.declaration.abi.sway",
679 | "match": "\\b(abi)\\b"
680 | },
681 | {
682 | "comment": "struct keyword",
683 | "name": "keyword.declaration.struct.sway",
684 | "match": "\\b(struct)\\b"
685 | },
686 | {
687 | "comment": "storage modifiers",
688 | "name": "storage.modifier.sway",
689 | "match": "\\b(abstract|static)\\b"
690 | },
691 | {
692 | "comment": "other keywords",
693 | "name": "keyword.other.sway",
694 | "match": "\\b(as|async|become|box|dyn|move|final|impl|in|override|priv|pub|ref|typeof|union|unsafe|unsized|use|virtual|where)\\b"
695 | },
696 | {
697 | "comment": "fn",
698 | "name": "keyword.other.fn.sway",
699 | "match": "\\bfn\\b"
700 | },
701 | {
702 | "comment": "asm",
703 | "name": "keyword.other.asm.sway",
704 | "match": "\\basm\\b"
705 | },
706 | {
707 | "comment": "crate",
708 | "name": "keyword.other.crate.sway",
709 | "match": "\\bcrate\\b"
710 | },
711 | {
712 | "comment": "mut",
713 | "name": "storage.modifier.mut.sway",
714 | "match": "\\bmut\\b"
715 | },
716 | {
717 | "comment": "logical operators",
718 | "name": "keyword.operator.logical.sway",
719 | "match": "(\\^|\\||\\|\\||&&|<<|>>|!)(?!=)"
720 | },
721 | {
722 | "comment": "logical AND, borrow references",
723 | "name": "keyword.operator.borrow.and.sway",
724 | "match": "&(?![&=])"
725 | },
726 | {
727 | "comment": "assignment operators",
728 | "name": "keyword.operator.assignment.sway",
729 | "match": "(\\+=|-=|\\*=|/=|%=|\\^=|&=|\\|=|<<=|>>=)"
730 | },
731 | {
732 | "comment": "single equal",
733 | "name": "keyword.operator.assignment.equal.sway",
734 | "match": "(?])=(?!=|>)"
735 | },
736 | {
737 | "comment": "comparison operators",
738 | "name": "keyword.operator.comparison.sway",
739 | "match": "(=(=)?(?!>)|!=|<=|(?=)"
740 | },
741 | {
742 | "comment": "math operators",
743 | "name": "keyword.operator.math.sway",
744 | "match": "(([+%]|(\\*(?!\\w)))(?!=))|(-(?!>))|(/(?!/))"
745 | },
746 | {
747 | "comment": "less than, greater than (special case)",
748 | "match": "(?:\\b|(?:(\\))|(\\])|(\\})))[ \\t]+([<>])[ \\t]+(?:\\b|(?:(\\()|(\\[)|(\\{)))",
749 | "captures": {
750 | "1": {
751 | "name": "punctuation.brackets.round.sway"
752 | },
753 | "2": {
754 | "name": "punctuation.brackets.square.sway"
755 | },
756 | "3": {
757 | "name": "punctuation.brackets.curly.sway"
758 | },
759 | "4": {
760 | "name": "keyword.operator.comparison.sway"
761 | },
762 | "5": {
763 | "name": "punctuation.brackets.round.sway"
764 | },
765 | "6": {
766 | "name": "punctuation.brackets.square.sway"
767 | },
768 | "7": {
769 | "name": "punctuation.brackets.curly.sway"
770 | }
771 | }
772 | },
773 | {
774 | "comment": "namespace operator",
775 | "name": "keyword.operator.namespace.sway",
776 | "match": "::"
777 | },
778 | {
779 | "comment": "dereference asterisk",
780 | "match": "(\\*)(?=\\w+)",
781 | "captures": {
782 | "1": {
783 | "name": "keyword.operator.dereference.sway"
784 | }
785 | }
786 | },
787 | {
788 | "comment": "subpattern binding",
789 | "name": "keyword.operator.subpattern.sway",
790 | "match": "@"
791 | },
792 | {
793 | "comment": "dot access",
794 | "name": "keyword.operator.access.dot.sway",
795 | "match": "\\.(?!\\.)"
796 | },
797 | {
798 | "comment": "ranges, range patterns",
799 | "name": "keyword.operator.range.sway",
800 | "match": "\\.{2}(=|\\.)?"
801 | },
802 | {
803 | "comment": "colon",
804 | "name": "keyword.operator.key-value.sway",
805 | "match": ":(?!:)"
806 | },
807 | {
808 | "comment": "dashrocket, skinny arrow",
809 | "name": "keyword.operator.arrow.skinny.sway",
810 | "match": "->"
811 | },
812 | {
813 | "comment": "hashrocket, fat arrow",
814 | "name": "keyword.operator.arrow.fat.sway",
815 | "match": "=>"
816 | },
817 | {
818 | "comment": "dollar macros",
819 | "name": "keyword.operator.macro.dollar.sway",
820 | "match": "\\$"
821 | },
822 | {
823 | "comment": "question mark operator, questionably sized, macro kleene matcher",
824 | "name": "keyword.operator.question.sway",
825 | "match": "\\?"
826 | }
827 | ]
828 | },
829 | "interpolations": {
830 | "comment": "curly brace interpolations",
831 | "name": "meta.interpolation.sway",
832 | "match": "({)[^\"{}]*(})",
833 | "captures": {
834 | "1": {
835 | "name": "punctuation.definition.interpolation.sway"
836 | },
837 | "2": {
838 | "name": "punctuation.definition.interpolation.sway"
839 | }
840 | }
841 | },
842 | "lifetimes": {
843 | "patterns": [
844 | {
845 | "comment": "named lifetime parameters",
846 | "match": "(['])([a-zA-Z_][0-9a-zA-Z_]*)(?!['])\\b",
847 | "captures": {
848 | "1": {
849 | "name": "punctuation.definition.lifetime.sway"
850 | },
851 | "2": {
852 | "name": "entity.name.type.lifetime.sway"
853 | }
854 | }
855 | },
856 | {
857 | "comment": "borrowing references to named lifetimes",
858 | "match": "(\\&)(['])([a-zA-Z_][0-9a-zA-Z_]*)(?!['])\\b",
859 | "captures": {
860 | "1": {
861 | "name": "keyword.operator.borrow.sway"
862 | },
863 | "2": {
864 | "name": "punctuation.definition.lifetime.sway"
865 | },
866 | "3": {
867 | "name": "entity.name.type.lifetime.sway"
868 | }
869 | }
870 | }
871 | ]
872 | },
873 | "macros": {
874 | "patterns": [
875 | {
876 | "comment": "macros",
877 | "name": "meta.macro.sway",
878 | "match": "(([a-z_][A-Za-z0-9_]*!)|([A-Z_][A-Za-z0-9_]*!))",
879 | "captures": {
880 | "2": {
881 | "name": "entity.name.function.macro.sway"
882 | },
883 | "3": {
884 | "name": "entity.name.type.macro.sway"
885 | }
886 | }
887 | }
888 | ]
889 | },
890 | "namespaces": {
891 | "patterns": [
892 | {
893 | "comment": "namespace (non-type, non-function path segment)",
894 | "match": "(?",
929 | "endCaptures": {
930 | "0": {
931 | "name": "punctuation.brackets.angle.sway"
932 | }
933 | },
934 | "patterns": [
935 | {
936 | "include": "#block-comments"
937 | },
938 | {
939 | "include": "#comments"
940 | },
941 | {
942 | "include": "#keywords"
943 | },
944 | {
945 | "include": "#lvariables"
946 | },
947 | {
948 | "include": "#lifetimes"
949 | },
950 | {
951 | "include": "#punctuation"
952 | },
953 | {
954 | "include": "#types"
955 | },
956 | {
957 | "include": "#variables"
958 | }
959 | ]
960 | },
961 | {
962 | "comment": "primitive types",
963 | "name": "entity.name.type.primitive.sway",
964 | "match": "\\b(bool|char|str)\\b"
965 | },
966 | {
967 | "comment": "trait declarations",
968 | "match": "\\b(trait)\\s+([A-Z][A-Za-z0-9]*)\\b",
969 | "captures": {
970 | "1": {
971 | "name": "keyword.declaration.trait.sway"
972 | },
973 | "2": {
974 | "name": "entity.name.type.trait.sway"
975 | }
976 | }
977 | },
978 | {
979 | "comment": "abi declarations",
980 | "match": "\\b(abi)\\s+([A-Z][A-Za-z0-9]*)\\b",
981 | "captures": {
982 | "1": {
983 | "name": "keyword.declaration.abi.sway"
984 | },
985 | "2": {
986 | "name": "entity.name.type.abi.sway"
987 | }
988 | }
989 | },
990 | {
991 | "comment": "struct declarations",
992 | "match": "\\b(struct)\\s+([A-Z][A-Za-z0-9]*)\\b",
993 | "captures": {
994 | "1": {
995 | "name": "keyword.declaration.struct.sway"
996 | },
997 | "2": {
998 | "name": "entity.name.type.struct.sway"
999 | }
1000 | }
1001 | },
1002 | {
1003 | "comment": "enum declarations",
1004 | "match": "\\b(enum)\\s+([A-Z][A-Za-z0-9_]*)\\b",
1005 | "captures": {
1006 | "1": {
1007 | "name": "keyword.declaration.enum.sway"
1008 | },
1009 | "2": {
1010 | "name": "entity.name.type.enum.sway"
1011 | }
1012 | }
1013 | },
1014 | {
1015 | "comment": "type declarations",
1016 | "match": "\\b(type)\\s+([A-Z][A-Za-z0-9_]*)\\b",
1017 | "captures": {
1018 | "1": {
1019 | "name": "keyword.declaration.type.sway"
1020 | },
1021 | "2": {
1022 | "name": "entity.name.type.declaration.sway"
1023 | }
1024 | }
1025 | },
1026 | {
1027 | "comment": "types",
1028 | "name": "entity.name.type.sway",
1029 | "match": "\\b[A-Z][A-Za-z0-9]*\\b(?!!)"
1030 | },
1031 | {
1032 | "comment": "top level declaration",
1033 | "begin": "\\b(library)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
1034 | "end": "[\\{\\(;]",
1035 | "beginCaptures": {
1036 | "1": {
1037 | "name": "source.sway meta.attribute.sway"
1038 | },
1039 | "2": {
1040 | "name": "entity.name.type.sway"
1041 | }
1042 | },
1043 | "patterns": [
1044 | {
1045 | "include": "#block-comments"
1046 | },
1047 | {
1048 | "include": "#comments"
1049 | },
1050 | {
1051 | "include": "#keywords"
1052 | },
1053 | {
1054 | "include": "#namespaces"
1055 | },
1056 | {
1057 | "include": "#punctuation"
1058 | },
1059 | {
1060 | "include": "#types"
1061 | },
1062 | {
1063 | "include": "#lvariables"
1064 | }
1065 | ]
1066 | },
1067 | {
1068 | "comment": "top level declaration without name",
1069 | "match": "(contract|script|predicate);",
1070 | "captures": {
1071 | "1": {
1072 | "name": "source.sway meta.attribute.sway"
1073 | }
1074 | }
1075 | }
1076 | ]
1077 | },
1078 | "gtypes": {
1079 | "patterns": [
1080 | {
1081 | "comment": "option types",
1082 | "name": "entity.name.type.option.sway",
1083 | "match": "\\b(Some|None)\\b"
1084 | },
1085 | {
1086 | "comment": "result types",
1087 | "name": "entity.name.type.result.sway",
1088 | "match": "\\b(Ok|Err)\\b"
1089 | }
1090 | ]
1091 | },
1092 | "punctuation": {
1093 | "patterns": [
1094 | {
1095 | "comment": "comma",
1096 | "name": "punctuation.comma.sway",
1097 | "match": ","
1098 | },
1099 | {
1100 | "comment": "curly braces",
1101 | "name": "punctuation.brackets.curly.sway",
1102 | "match": "[{}]"
1103 | },
1104 | {
1105 | "comment": "parentheses, round brackets",
1106 | "name": "punctuation.brackets.round.sway",
1107 | "match": "[()]"
1108 | },
1109 | {
1110 | "comment": "semicolon",
1111 | "name": "punctuation.semi.sway",
1112 | "match": ";"
1113 | },
1114 | {
1115 | "comment": "square brackets",
1116 | "name": "punctuation.brackets.square.sway",
1117 | "match": "[\\[\\]]"
1118 | },
1119 | {
1120 | "comment": "angle brackets",
1121 | "name": "punctuation.brackets.angle.sway",
1122 | "match": "(?]"
1123 | }
1124 | ]
1125 | },
1126 | "strings": {
1127 | "patterns": [
1128 | {
1129 | "comment": "double-quoted strings and byte strings",
1130 | "name": "string.quoted.double.sway",
1131 | "begin": "(b?)(\")",
1132 | "beginCaptures": {
1133 | "1": {
1134 | "name": "string.quoted.byte.raw.sway"
1135 | },
1136 | "2": {
1137 | "name": "punctuation.definition.string.sway"
1138 | }
1139 | },
1140 | "end": "\"",
1141 | "endCaptures": {
1142 | "0": {
1143 | "name": "punctuation.definition.string.sway"
1144 | }
1145 | },
1146 | "patterns": [
1147 | {
1148 | "include": "#escapes"
1149 | },
1150 | {
1151 | "include": "#interpolations"
1152 | }
1153 | ]
1154 | },
1155 | {
1156 | "comment": "double-quoted raw strings and raw byte strings",
1157 | "name": "string.quoted.double.sway",
1158 | "begin": "(b?r)(#*)(\")",
1159 | "beginCaptures": {
1160 | "1": {
1161 | "name": "string.quoted.byte.raw.sway"
1162 | },
1163 | "2": {
1164 | "name": "punctuation.definition.string.raw.sway"
1165 | },
1166 | "3": {
1167 | "name": "punctuation.definition.string.sway"
1168 | }
1169 | },
1170 | "end": "(\")(\\2)",
1171 | "endCaptures": {
1172 | "1": {
1173 | "name": "punctuation.definition.string.sway"
1174 | },
1175 | "2": {
1176 | "name": "punctuation.definition.string.raw.sway"
1177 | }
1178 | }
1179 | },
1180 | {
1181 | "comment": "characters and bytes",
1182 | "name": "string.quoted.single.char.sway",
1183 | "begin": "(b)?(')",
1184 | "beginCaptures": {
1185 | "1": {
1186 | "name": "string.quoted.byte.raw.sway"
1187 | },
1188 | "2": {
1189 | "name": "punctuation.definition.char.sway"
1190 | }
1191 | },
1192 | "end": "'",
1193 | "endCaptures": {
1194 | "0": {
1195 | "name": "punctuation.definition.char.sway"
1196 | }
1197 | },
1198 | "patterns": [
1199 | {
1200 | "include": "#escapes"
1201 | }
1202 | ]
1203 | }
1204 | ]
1205 | },
1206 | "lvariables": {
1207 | "patterns": [
1208 | {
1209 | "comment": "self",
1210 | "name": "variable.language.self.sway",
1211 | "match": "\\b[Ss]elf\\b"
1212 | },
1213 | {
1214 | "comment": "super",
1215 | "name": "variable.language.super.sway",
1216 | "match": "\\bsuper\\b"
1217 | }
1218 | ]
1219 | },
1220 | "variables": {
1221 | "patterns": [
1222 | {
1223 | "comment": "variables",
1224 | "name": "variable.other.sway",
1225 | "match": "\\b(?