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

Virtual File Systems & Shopify Liquid VS Code extension for Web #529

Merged
merged 31 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3ce9b46
Simplify theme-language-server-browser connection creation
charlespwd Oct 9, 2024
9a141df
Add VS Code for Web Extension skeleton implementation
charlespwd Oct 9, 2024
9d252ba
Remove support for ruby-based language server
charlespwd Oct 9, 2024
b9b96c1
Add VS Code for Web major bump changeset
charlespwd Oct 9, 2024
f352ee8
Fixup the sourcemaps & launch.json for dual build
charlespwd Oct 10, 2024
f47c48b
Clean up asset-size-based tests
charlespwd Oct 10, 2024
69c8fcb
Include theme check test helpers in dist
charlespwd Oct 10, 2024
3849c34
Replace `fileExists` dependency by `fs` injection
charlespwd Oct 10, 2024
2e7b289
Get rid of the fileSize injection (use abstract `fs.stat` instead)
charlespwd Oct 13, 2024
ad8162d
Replace getDefault(Schema)?Locale dependency injection
charlespwd Oct 15, 2024
f611b78
Rename FileSystem to AbstractFileSystem
charlespwd Oct 15, 2024
c0e1048
Replace AbsolutePath concern in theme-check-common
charlespwd Oct 15, 2024
24ed13c
Fixup baseUrl in tcn
charlespwd Oct 15, 2024
5d222f2
Normalize URIs for windows and remove back slashes of relative paths
charlespwd Oct 15, 2024
a40ceac
Uri->UriString for clarity
charlespwd Oct 15, 2024
8d5c413
Remove getDefault(Schema)?Translations dependencies
charlespwd Oct 16, 2024
fc7cb9a
Move buffer translations concern to theme-check-common
charlespwd Oct 16, 2024
4dcc202
Remove filesForURI language server dependency
charlespwd Oct 16, 2024
323ba07
Remove getThemeSettingsSchemaForURI injection
charlespwd Oct 16, 2024
a016347
Remove findRootURI injection
charlespwd Oct 16, 2024
18c95dd
Implement and setup basic VsCodeFileSystem
charlespwd Oct 16, 2024
9840c50
Optimize FS calls in the Language Server
charlespwd Oct 17, 2024
32c11f4
Implement MainThreadFileSystem in CodeMirror Playground
charlespwd Oct 17, 2024
81b6782
Add a bunch of changesets
charlespwd Oct 17, 2024
f2f3c0e
Docs changes and webpack config cleanup
charlespwd Oct 17, 2024
b77e59d
Add toplevel `yarn dev:web` command
charlespwd Oct 18, 2024
6e2b36e
Minor cleanups
charlespwd Oct 18, 2024
a76b2b2
Add Debug Web Extension in Chromium launch config
charlespwd Oct 23, 2024
56d92fb
Add support for prettier formatting in web/remote contexts
charlespwd Oct 24, 2024
1f173a1
PR Cleanups
charlespwd Oct 25, 2024
6ef16d6
All dev servers on :3000
charlespwd Oct 25, 2024
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
15 changes: 15 additions & 0 deletions .changeset/curly-books-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@shopify/theme-check-common': major
'@shopify/theme-language-server-common': major
---

[Breaking] Replace absolute path concerns with URIs

This implies a couple of changes:
- `Config` now holds a `rootUri` instead of `root` path.
- `loadConfig` injections needs to change their return value accordingly
- In checks,
- The context helper `absolutePath` has been replaced by `toUri`
- The context helper `relativePath` has been replaced by `toRelativePath`
- `SourceCode` objects now hold a `uri` instead of a `path`
- `toSourceCode` now accepts a `uri` instead of a `path`
5 changes: 5 additions & 0 deletions .changeset/dry-adults-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/codemirror-language-client': minor
---

Expose language client in CodeMirrorLanguageClient
21 changes: 21 additions & 0 deletions .changeset/hungry-cups-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
'@shopify/theme-check-browser': major
'@shopify/theme-check-common': major
'@shopify/theme-check-node': major
---

[Breaking] Replace fs-based dependency injections with AbstractFileSystem injection

```diff
runChecks(theme, {
- getDefaultTranslations,
- getDefaultLocale,
- getDefaultSchemaLocale,
- getDefaultSchemaTranslations,
- fileExists,
- fileSize,
+ fs: new FileSystemImpl(),
themeDocset,
jsonValidationSet,
})
```
10 changes: 10 additions & 0 deletions .changeset/light-ways-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'theme-check-vscode': major
---

Add support for virtual file systems

The Shopify Liquid VS Code extension now works in a large set of new environments:
- Remote files
- Git backed files
- VS Code for the Web
29 changes: 29 additions & 0 deletions .changeset/moody-turkeys-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
'@shopify/theme-language-server-browser': major
'@shopify/theme-language-server-common': major
'@shopify/theme-language-server-node': major
---

[Breaking] Replace fs-based dependency injection by an AbstractFileSystem injection

```diff
+ class FileSystemImpl implements AbstractFileSystem {
+ /* ... */
+ }

startServer(worker, {
- findRootURI,
- fileExists,
- fileSize,
- getDefaultTranslationsFactory,
- getDefaultLocaleFactory,
- getDefaultSchemaTranslationsFactory,
- getDefaultSchemaLocaleFactory,
- getThemeSettingsSchemaForRootURI,
+ fs: new FileSystemImpl(),
loadConfig,
log,
themeDocset,
jsonValidationSet,
})
```
5 changes: 5 additions & 0 deletions .changeset/silent-comics-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'theme-check-vscode': major
---

[BREAKING] Remove support for ruby language server
26 changes: 26 additions & 0 deletions .changeset/stale-swans-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
'@shopify/theme-language-server-browser': major
'@shopify/theme-language-server-node': major
---

Expose language server connection in Public API

This lets you send non-standard LSP messages to the client.

```ts
import { getConnection, startServer, AbstractFileSystem } from '@shopify/theme-language-server-browser'

class MainThreadFileSystem implements AbstractFileSystem {
constructor(private connection) {}
readFile(uri) { return this.connection.sendRequest('fs/readFile', uri); }
readDirectory(uri) { return this.connection.sendRequest('fs/readDirectory', uri); }
readFile(uri) { return this.connection.sendRequest('fs/stat', uri); }
}

const worker = self as any as Worker;
const connection = getConnection(worker);
const fs = new MainThreadFileSystem(connection);
const dependencies = { /* ... */ };

startServer(worker, dependencies, connection);
```
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ package-lock.json
.npmrc
packages/theme-check-docs-updater/data
packages/lang-jsonc/src/parser.*
.vscode-test-web
34 changes: 31 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
{
"type": "extensionHost",
"request": "launch",
"name": "Launch Client",
"name": "Debug Node Extension",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}/packages/vscode-extension"
],
"autoAttachChildProcesses": true,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/packages/vscode-extension/dist/**/*.js",
"${workspaceRoot}/packages/vscode-extension/dist/node/**/*.js",
"${workspaceRoot}/packages/theme-language-server-common/dist/**/*.js",
"${workspaceRoot}/packages/theme-language-server-node/dist/**/*.js",
"${workspaceRoot}/packages/theme-check-common/dist/**/*.js",
Expand All @@ -27,10 +27,38 @@
],
"preLaunchTask": "vscode dev"
},
{
"name": "Debug Web Extension",
"type": "extensionHost",
"debugWebWorkerHost": true,
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-extension",
"--extensionDevelopmentKind=web"
],
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/packages/vscode-extension/dist/browser/**/*.js",
"${workspaceRoot}/packages/theme-language-server-common/dist/**/*.js",
"${workspaceRoot}/packages/theme-language-server-browser/dist/**/*.js",
"${workspaceRoot}/packages/theme-check-common/dist/**/*.js",
"${workspaceRoot}/packages/theme-check-browser/dist/**/*.js",
"${workspaceRoot}/packages/prettier-plugin-liquid/dist/**/*.js",
"${workspaceRoot}/packages/liquid-html-parser/dist/**/*.js",
],
"preLaunchTask": "vscode dev"
},
{
"name": "Debug Web Extension in Chromium",
"type": "chrome",
"request": "attach",
"url": "http://localhost:3000",
charlespwd marked this conversation as resolved.
Show resolved Hide resolved
"preLaunchTask": "vscode-test-web"
},
{
"type": "chrome",
"request": "launch",
"name": "Debug playground",
"name": "Debug CodeMirror playground",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}/packages/codemirror-language-client/playground",
"outFiles": [
Expand Down
7 changes: 7 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
"command": "yarn playground",
"isBackground": true,
"problemMatcher": "$ts-webpack-watch"
},
{
"label": "vscode-test-web",
"type": "shell",
"command": "yarn dev:web",
"isBackground": true,
"problemMatcher": "$ts-webpack-watch"
}
],
}
16 changes: 16 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,22 @@ Run the following command to start a browser instance that runs `@shopify/theme-
yarn playground
```

### Developing for VS Code for Web

#### In Chrome

Run the following command to start a `@vscode/test-web` instance in Chrome with the Shopify Liquid extension loaded.

```bash
yarn dev:web
```

#### In the desktop app

Because the Chrome version doesn't have great debugging, you can also use the `Run Web Extension` Launch configuration to debug the extension.

This starts a Extension Host window like the normal `F5` flow, but instead of running the node extension, it's running the browser extension.

### Testing JSON Schema changes on Shopify/theme-liquid-docs

If ever you want to see how the VS Code extension or playground would behave before merging a PR to Shopify/theme-liquid-docs, you can do the following:
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"build": "yarn workspaces run build",
"build:ci": "yarn workspaces run build:ci",
"build:ts": "yarn workspaces run build:ts",
"dev:web": "yarn --cwd packages/vscode-extension dev:web",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glob package fails if you don't have node v20-22. Could we add an .nvmrc to have v22?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Durr I have a .nvmrc but I git ignored/excluded it? Yeah def should do

"format": "prettier --write \"packages/*/src/**/*.ts\"",
"format:check": "prettier --check --ignore-unknown \"packages/*/src/**/*.ts\"",
"playground": "yarn --cwd packages/codemirror-language-client run dev:playground",
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { Dependencies, allChecks, startServer } from '@shopify/theme-language-server-browser';
import { URI } from 'vscode-languageserver-types';
import { isDependencyInjectionMessage } from './messages';
import {
Dependencies,
allChecks,
getConnection,
startServer,
AbstractFileSystem,
FileTuple,
FileStat,
} from '@shopify/theme-language-server-browser';
import { Connection } from 'vscode-languageserver';

/**
* These are replaced at build time by the contents of
Expand All @@ -22,74 +29,52 @@ const schemas = WEBPACK_SCHEMAS;

const worker = self as any as Worker;

// The file tree is provided from the main thread as an array of strings.
// The default translations are provided from the main thread.
let files: Set<string>;
let defaultTranslations: any = {};
worker.addEventListener('message', (ev) => {
const message = ev.data;
if (!isDependencyInjectionMessage(message)) return;

switch (message.method) {
case 'shopify/setDefaultTranslations': {
return (defaultTranslations = message.params);
}
case 'shopify/setFileTree': {
return (files = new Set(message.params));
}
}
const loadConfig: Dependencies['loadConfig'] = async (_uri, fileExists) => ({
context: 'theme',
settings: {},
checks: allChecks,
rootUri: 'browser:/',
});

async function fileExists(path: string) {
return files && files.has(path);
}
const connection = getConnection(worker);

function getDefaultTranslationsFactory(_uri: string) {
return async () => defaultTranslations as any;
}
class MainThreadFileSystem implements AbstractFileSystem {
constructor(private connection: Connection) {
this.connection = connection;
}

// pretending they are the same :upside_down_smile:
function getDefaultSchemaTranslationsFactory(_uri: string) {
return async () => defaultTranslations as any;
}
async readFile(uri: string) {
return this.connection.sendRequest('fs/readFile', uri) as Promise<string>;
}

function getThemeSettingsSchemaForRootURI(_rootURI: URI) {
return [] as any;
}
async readDirectory(uri: string) {
return this.connection.sendRequest('fs/readDirectory', uri) as Promise<FileTuple[]>;
}

async function findRootURI(_uri: string) {
return 'browser:/';
async stat(uri: string) {
return this.connection.sendRequest('fs/stat', uri) as Promise<FileStat>;
}
}

const loadConfig: Dependencies['loadConfig'] = async (_uri) => ({
context: 'theme',
settings: {},
checks: allChecks,
root: '/',
});

startServer(worker, {
fileSize: async (_: string) => 42,
fileExists,
findRootURI,
getDefaultTranslationsFactory,
getDefaultSchemaTranslationsFactory,
getThemeSettingsSchemaForRootURI,
getDefaultLocaleFactory: (_: string) => async () => 'en',
getDefaultSchemaLocaleFactory: (_: string) => async () => 'en',
themeDocset: {
filters: async () => filters,
tags: async () => tags,
objects: async () => objects,
systemTranslations: async () => systemTranslations,
},
jsonValidationSet: {
schemas: async () => schemas,
startServer(
worker,
{
fs: new MainThreadFileSystem(connection),
themeDocset: {
filters: async () => filters,
tags: async () => tags,
objects: async () => objects,
systemTranslations: async () => systemTranslations,
},
jsonValidationSet: {
schemas: async () => schemas,
},
loadConfig,
log(message) {
console.info(message);
},
},
loadConfig,
log(message) {
console.info(message);
},
});
connection,
);

export {};
25 changes: 0 additions & 25 deletions packages/codemirror-language-client/playground/src/messages.ts

This file was deleted.

Loading
Loading