Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document symbols feature #25

Merged
merged 23 commits into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
# Overview

This project is an early proof of concept of a language server for Sass written in Dart to make use of [sass_api](https://pub.dev/packages/sass_api). The proof of concept includes:
This is a work-in-progress language server for Sass written in Dart to
use [sass_api](https://pub.dev/packages/sass_api).

- Language server process with incremental document sync.
- User configuration.
- [Document links](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentLink) provider.
- Workspace scanner.
- VS Code client with debugging profile.

Check the documentation to get started:
See the [initial version roadmap](https://github.com/sass/dart-sass-language-server/issues/2) for the state of different features or check the documentation to get started:

- [Development environment](./docs/contributing/development-environment.md)
- [Debugging](./docs/contributing/debugging.md)
- [Testing and debugging](./docs/contributing/testing-and-debugging.md)
- [Building](./docs/contributing/building.md)
- [Architecture](./docs/contributing/architecture.md)
4 changes: 3 additions & 1 deletion docs/contributing/development-environment.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## Development environment

The Sass language server, like the Sass compiler, is written in [Dart](https://dart.dev/). The language extension for Visual Studio Code is written in [TypeScript](https://www.typescriptlang.org/).
The Sass language server, like the Sass compiler, is written in [Dart](https://dart.dev/).
The language extension for Visual Studio Code is written in [TypeScript](https://www.typescriptlang.org/).
Tests for the extension are written in JavaScript.

If you have a background writing JavaScript or TypeScript, [Learning Dart as a JavaScript developer](https://dart.dev/resources/coming-from/js-to-dart) is a great place to start.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Debugging
# Testing and debugging

Here we assume you have set up a [development environment](./development-environment.md).

Expand All @@ -13,6 +13,16 @@ The quickest way to test the language server is to debug the language extension

This will open another window of Visual Studio Code, this one running as an `[Extension Development Host]`.

### Testing in isolation

VS Code ships with some built-in support for SCSS and CSS. To test this language server in isolation you can disable the built-in extension.

1. Go to the Extensions tab and search for `@builtin css language features`.
2. Click the settings icon and pick Disable from the list.
3. Click Restart extension to turn it off.

You should also turn off extensions like SCSS IntelliSense or Some Sass.

### Open the Dart DevTools

In this configuration, the client has run `dart run --observe` in the local `sass_language_server` package. You can now use [Dart DevTools](https://dart.dev/tools/dart-devtools) to debug the language server.
Expand Down Expand Up @@ -61,13 +71,3 @@ test profile in the Run and Debug view in VS Code.
]
}
```

## Testing in isolation

VS Code ships with some built-in support for SCSS and CSS. To test this language server in isolation you can disable the built-in extension.

1. Go to the Extensions tab and search for `@builtin css language features`.
2. Click the settings icon and pick Disable from the list.
3. Click Restart extension to turn it off.

You should also turn off extensions like SCSS IntelliSense or Some Sass.
47 changes: 34 additions & 13 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@
"type": "string"
},
"default": [
"**/.git/**",
"**/node_modules/**"
".git/**",
"node_modules/**"
],
"description": "List of glob patterns for directories that are excluded when scanning.",
"description": "List of glob patterns for files that are excluded when scanning.",
"order": 1
},
"sass.workspace.logLevel": {
Expand Down Expand Up @@ -213,6 +213,13 @@
"default": true,
"description": "Enable or disable all diagnostics."
},
"sass.scss.documentSymbols.enabled": {
"order": 55,
"type": "boolean",
"scope": "resource",
"default": true,
"description": "Enable or disable Document symbols."
},
"sass.scss.foldingRanges.enabled": {
"order": 60,
"type": "boolean",
Expand Down Expand Up @@ -248,7 +255,7 @@
"default": true,
"description": "Show references to Sass documentation for Sass built-in modules and SassDoc for annotations."
},
"sass.scss.links.enabled": {
"sass.scss.documentLinks.enabled": {
"order": 90,
"type": "boolean",
"scope": "resource",
Expand Down Expand Up @@ -283,7 +290,7 @@
"default": true,
"description": "Enable or disable signature help."
},
"sass.scss.workspaceSymbol.enabled": {
"sass.scss.workspaceSymbols.enabled": {
"order": 140,
"type": "boolean",
"scope": "resource",
Expand Down Expand Up @@ -371,6 +378,13 @@
"default": true,
"description": "Enable or disable all diagnostics."
},
"sass.sass.documentSymbols.enabled": {
"order": 55,
"type": "boolean",
"scope": "resource",
"default": true,
"description": "Enable or disable Document symbols."
},
"sass.sass.foldingRanges.enabled": {
"order": 60,
"type": "boolean",
Expand Down Expand Up @@ -406,7 +420,7 @@
"default": true,
"description": "Show references to MDN in CSS hovers, Sass documentation for Sass built-in modules and SassDoc for annotations."
},
"sass.sass.links.enabled": {
"sass.sass.documentLinks.enabled": {
"order": 90,
"type": "boolean",
"scope": "resource",
Expand Down Expand Up @@ -439,14 +453,14 @@
"type": "boolean",
"scope": "resource",
"default": true,
"description": "Enable or disable selection ranges."
"description": "Enable or disable signature help."
},
"sass.sass.workspaceSymbol.enabled": {
"sass.sass.workspaceSymbols.enabled": {
"order": 140,
"type": "boolean",
"scope": "resource",
"default": true,
"description": "Enable or disable selection ranges."
"description": "Enable or disable workspace symbols."
}
}
},
Expand Down Expand Up @@ -502,6 +516,13 @@
"default": false,
"description": "Enable or disable all diagnostics."
},
"sass.css.documentSymbols.enabled": {
"order": 55,
"type": "boolean",
"scope": "resource",
"default": true,
"description": "Enable or disable Document symbols."
},
"sass.css.foldingRanges.enabled": {
"order": 60,
"type": "boolean",
Expand Down Expand Up @@ -537,7 +558,7 @@
"default": true,
"description": "Show references to MDN in CSS hovers."
},
"sass.css.links.enabled": {
"sass.css.documentLinks.enabled": {
"order": 90,
"type": "boolean",
"scope": "resource",
Expand Down Expand Up @@ -570,14 +591,14 @@
"type": "boolean",
"scope": "resource",
"default": false,
"description": "Enable or disable selection ranges."
"description": "Enable or disable signature help."
},
"sass.css.workspaceSymbol.enabled": {
"sass.css.workspaceSymbols.enabled": {
"order": 140,
"type": "boolean",
"scope": "resource",
"default": false,
"description": "Enable or disable selection ranges."
"description": "Enable or disable workspace symbols."
}
}
}
Expand Down
52 changes: 52 additions & 0 deletions extension/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,58 @@ export async function activate(context: ExtensionContext): Promise<void> {
}
}
});

// TODO: Maybe worth looking into so links to built-ins resolve to something?
// workspace.registerFileSystemProvider(
// 'sass',
// {
// readFile(uri) {
// return Uint8Array.from(
// '@function hello();'.split('').map((c) => c.charCodeAt(0))
// );
// },
// watch(uri, options) {
// return Disposable.create(() => {
// console.log('hello');
// });
// },
// readDirectory(uri) {
// return [];
// },
// stat(uri) {
// return {
// ctime: 0,
// mtime: 0,
// size: 0,
// type: 1,
// };
// },
// writeFile(uri, content, options) {
// return;
// },
// createDirectory(uri) {
// return;
// },
// delete(uri, options) {
// return;
// },
// rename(oldUri, newUri, options) {
// return;
// },
// copy(source, destination, options) {
// return;
// },
// onDidChangeFile(e) {
// return Disposable.create(() => {
// console.log('hello');
// });
// },
// },
// {
// isCaseSensitive: false,
// isReadonly: true,
// }
// );
}

export async function deactivate(): Promise<void> {
Expand Down
15 changes: 15 additions & 0 deletions extension/test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Testing the VS Code extension

These tests automate Visual Studio Code using the [VS Code JavaScript API](https://code.visualstudio.com/api/references/vscode-api).
See [the list of built-in commands](https://code.visualstudio.com/api/references/commands#commands) to see how you can automate the interactions you need for testing.

The runner is configured so it can run multiple instances of VS Code (in sequence) using different configurations and workspaces.
Each subdirectory in `electron/` will run in a separate instance of VS Code.

By convention subdirectories in `electron/` should have:

- `index.js` as the entrypoint that finds test files and passes them to Mocha
- at least one `*.test.js` file with some tests
- a `fixtures/` subdirectory with:
- `.vscode/settings.json`
- `styles.scss` or `styles.sass`
38 changes: 38 additions & 0 deletions extension/test/electron/document-symbols/document-symbols.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const assert = require('node:assert');
const path = require('node:path');
const vscode = require('vscode');
const { showFile, sleepCI } = require('../util');

const stylesUri = vscode.Uri.file(
path.resolve(__dirname, 'fixtures', 'styles.sass')
);

before(async () => {
await showFile(stylesUri);
await sleepCI();
});

after(async () => {
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
});

/**
* @param {import('vscode').Uri} documentUri
* @returns {Promise<import('vscode').DocumentSymbol[]>}
*/
async function findDocumentSymbols(documentUri) {
const result = await vscode.commands.executeCommand(
'vscode.executeDocumentSymbolProvider',
documentUri
);
return result;
}

test('gets CSS selectors', async () => {
const result = await findDocumentSymbols(stylesUri);

assert.ok(
result.find((s) => s.name === '.card .body:has(:not(.stuff))'),
'Should have found .card .body:has(:not(.stuff))'
);
});
17 changes: 17 additions & 0 deletions extension/test/electron/document-symbols/fixtures/styles.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
button
border-color: red

.hello
color: green

.world
color: blue

.card > .header,
.card > .body,
.card > .footer
padding: 2px


.card .body:has(:not(.stuff))
padding: 4px
25 changes: 25 additions & 0 deletions extension/test/electron/document-symbols/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const path = require('node:path');
const fs = require('node:fs/promises');
const vscode = require('vscode');
const { runMocha } = require('../mocha');

/**
* @returns {Promise<void>}
*/
async function run() {
const filePaths = [];

const dir = await fs.readdir(__dirname, { withFileTypes: true });
for (let entry of dir) {
if (entry.isFile() && entry.name.endsWith('test.js')) {
filePaths.push(path.join(entry.parentPath, entry.name));
}
}

await runMocha(
filePaths,
vscode.Uri.file(path.resolve(__dirname, 'fixtures', 'styles.sass'))
);
}

module.exports = { run };
Loading