Skip to content

Commit

Permalink
Feat(VSCode): Support monorepo workspaces and multiple configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
1aron committed May 8, 2024
1 parent 363b511 commit 4b31640
Show file tree
Hide file tree
Showing 25 changed files with 288 additions and 149 deletions.
6 changes: 5 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"sourceMaps": true,
"autoAttachChildProcesses": true,
"runtimeExecutable": "${execPath}",
"args": [
"--disable-extensions",
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode"
]
],
// todo: https://github.com/microsoft/vscode-eslint/blob/4d9fc40e71c403d359beaccdd4a6f8d027031513/.vscode/launch.json
// "preLaunchTask": "npm: watch"
}
]
}
17 changes: 9 additions & 8 deletions packages/eslint-plugin/src/utils/parse-node-recursive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'
* @param {Array} ignoredKeys Optional, set object keys which should not be parsed e.g. for `cva`
* @returns {void}
*/
export function parseNodeRecursive(rootNode, childNode, cb, skipConditional = false, isolate = false, ignoredKeys = [], context?: RuleContext<any, any>) {
export function parseNodeRecursive(rootNode, childNode, cb, skipConditional = false, isolate = false, ignoredKeys = [], context: RuleContext<any, any>) {
// TODO allow vue non litteral
let originalClassNamesValue
let classNames
Expand Down Expand Up @@ -55,7 +55,7 @@ export function parseNodeRecursive(rootNode, childNode, cb, skipConditional = fa
switch (childNode.type) {
case 'TemplateLiteral':
childNode.expressions.forEach((exp) => {
parseNodeRecursive(rootNode, exp, cb, skipConditional, forceIsolation, ignoredKeys)
parseNodeRecursive(rootNode, exp, cb, skipConditional, forceIsolation, ignoredKeys, context)
})
const sourceCode = context.sourceCode
originalClassNamesValue = sourceCode.getText(childNode)
Expand All @@ -66,15 +66,15 @@ export function parseNodeRecursive(rootNode, childNode, cb, skipConditional = fa
}
break
case 'ConditionalExpression':
parseNodeRecursive(rootNode, childNode.consequent, cb, skipConditional, forceIsolation, ignoredKeys)
parseNodeRecursive(rootNode, childNode.alternate, cb, skipConditional, forceIsolation, ignoredKeys)
parseNodeRecursive(rootNode, childNode.consequent, cb, skipConditional, forceIsolation, ignoredKeys, context)
parseNodeRecursive(rootNode, childNode.alternate, cb, skipConditional, forceIsolation, ignoredKeys, context)
return
case 'LogicalExpression':
parseNodeRecursive(rootNode, childNode.right, cb, skipConditional, forceIsolation, ignoredKeys)
parseNodeRecursive(rootNode, childNode.right, cb, skipConditional, forceIsolation, ignoredKeys, context)
return
case 'ArrayExpression':
childNode.elements.forEach((el) => {
parseNodeRecursive(rootNode, el, cb, skipConditional, forceIsolation, ignoredKeys)
parseNodeRecursive(rootNode, el, cb, skipConditional, forceIsolation, ignoredKeys, context)
})
return
case 'ObjectExpression':
Expand All @@ -97,12 +97,13 @@ export function parseNodeRecursive(rootNode, childNode, cb, skipConditional = fa
cb,
skipConditional,
forceIsolation,
ignoredKeys
ignoredKeys,
context
)
})
return
case 'Property':
parseNodeRecursive(rootNode, childNode.key, cb, skipConditional, forceIsolation, ignoredKeys)
parseNodeRecursive(rootNode, childNode.key, cb, skipConditional, forceIsolation, ignoredKeys, context)
return
case 'Literal':
trim = true
Expand Down
1 change: 1 addition & 0 deletions packages/language-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@master/css-explore-config": "workspace:^",
"@master/css-language-service": "workspace:^",
"@techor/extend": "^3.0.22",
"fast-glob": "^3.3.2",
"js-beautify": "^1.15.1",
"vscode-languageserver": "^9.0.1",
"vscode-languageserver-textdocument": "^1.0.11"
Expand Down
261 changes: 150 additions & 111 deletions packages/language-server/src/core.ts

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions packages/language-server/src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { settings as cssLanguageServiceSettings, type Settings as CSSLanguageSer

const settings: Settings = {
...cssLanguageServiceSettings,
config: 'master.css'
workspaces: 'auto'
}

export default settings

export declare type Settings = CSSLanguageServiceSettings | { config: string }
export declare type Settings = CSSLanguageServiceSettings & {
workspaces: string[] | 'auto'
}
4 changes: 4 additions & 0 deletions packages/language-server/tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ it('run server', async () => {
})

test.todo('modify and refresh config')
test.todo('detect monorepo workspaces')
test.todo('specify workspaces')
test.todo('workspace without any config file')
test.todo('multi-workspace config files')

afterAll(async () => {
await serverProcess.destroy()
Expand Down
12 changes: 11 additions & 1 deletion packages/language-service/playground/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
{}
{
"eslint.experimental.useFlatConfig": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html"
],
"masterCSS.workspaces": "auto"
}
21 changes: 21 additions & 0 deletions packages/language-service/playground/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import css from '@master/eslint-config-css/flat'
import htmlParser from '@angular-eslint/template-parser'
import tsParser from '@typescript-eslint/parser'

export default [
css,
{
files: [
'*.html'
],
languageOptions: {
parser: htmlParser
}
},
{
files: ['*.ts', '*.tsx', '*.js'],
languageOptions: {
parser: tsParser
}
}
]
3 changes: 2 additions & 1 deletion packages/language-service/playground/master.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default {
btn: `inline-flex text:center`
},
variables: {
foo: 123
foo: 123,
global: '#ff00ff'
}
} as Config
5 changes: 5 additions & 0 deletions packages/language-service/playground/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "vscode-playground",
"type": "module",
"private": true
}
1 change: 1 addition & 0 deletions packages/language-service/playground/packages/a/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="fg:custom"></div>
7 changes: 7 additions & 0 deletions packages/language-service/playground/packages/a/master.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Config } from '@master/css'

export default {
variables: {
custom: '#ff0000'
}
} as Config
1 change: 1 addition & 0 deletions packages/language-service/playground/packages/b/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="fg:custom"></div>
7 changes: 7 additions & 0 deletions packages/language-service/playground/packages/b/master.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Config } from '@master/css'

export default {
variables: {
custom: '#ffff00'
}
} as Config
1 change: 1 addition & 0 deletions packages/language-service/playground/packages/c/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="fg:global"></div>
4 changes: 4 additions & 0 deletions packages/language-service/playground/packages/c/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "vscode-playground-package-c",
"private": true
}
1 change: 1 addition & 0 deletions packages/language-service/playground/packages/d/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="fg:global"></div>
4 changes: 4 additions & 0 deletions packages/language-service/playground/packages/d/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "vscode-playground-package-c",
"private": true
}
2 changes: 1 addition & 1 deletion packages/language-service/playground/suggest-syntax.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="btn hidden fg:blue-5">
<div class="btn hidden fg:blue-5 fg:global">
hello world
</div>
4 changes: 2 additions & 2 deletions packages/language-service/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const SERVER_CAPABILITIES: ServerCapabilities = {
hoverProvider: true,
workspace: {
workspaceFolders: {
supported: true
}
supported: true,
},
}
}
2 changes: 0 additions & 2 deletions packages/language-service/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import EventEmitter from 'node:events'
import type { Position } from 'vscode-languageserver-protocol'
import settings, { type Settings } from './settings'
import { minimatch } from 'minimatch'
import { fileURLToPath } from 'node:url'
import inspectSyntax from './features/inspect-syntax'
import renderSyntaxColors from './features/render-syntax-colors'
import editSyntaxColors from './features/edit-syntax-colors'
import suggestSyntax from './features/suggest-syntax'
import { TextDocument } from 'vscode-languageserver-textdocument'
import findMatchingPairs from './utils/find-matching-brackets'
import escapeRegexp from 'lodash.escaperegexp'
import { normalize, posix, resolve } from 'node:path'

export type ClassPosition = { range: { start: number, end: number }, raw: string, token: string }

Expand Down
16 changes: 13 additions & 3 deletions packages/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@
"files": [
"dist"
],
"capabilities": {
"virtualWorkspaces": {
"supported": false,
"description": "Using Master CSS is not possible in virtual workspaces."
},
"untrustedWorkspaces": {
"supported": false,
"description": "The extension requires workspace trust because it loads configuration files and code from the workspace and executes it."
}
},
"contributes": {
"commands": [
{
Expand Down Expand Up @@ -239,9 +249,9 @@
"type": "boolean",
"default": true
},
"masterCSS.config": {
"type": "string",
"default": "master.css"
"masterCSS.workspaces": {
"type": [ "string", "array" ],
"default": "auto"
}
}
}
Expand Down
40 changes: 27 additions & 13 deletions packages/vscode/src/extension.min.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function activate(context: ExtensionContext) {

// The debug options for the server
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
const debugOptions = { execArgv: ['--nolazy', '--inspect=6010'] }
const debugOptions = { execArgv: ['--nolazy', '--inspect=6012'] }

// If the extension is launched in debug mode then the debug server options are used
// Otherwise the run options are used
Expand Down Expand Up @@ -56,30 +56,44 @@ export function activate(context: ExtensionContext) {
client.start()

const restart = async (options = {
title: 'Restarting Master CSS Language Server...'
title: 'Restarting Master CSS'
}) => {
window.withProgress({
await window.withProgress({
location: ProgressLocation.Notification,
title: options.title,
}, async () => await client.restart())
title: options.title
}, async (progress) => {
await client.restart()
const registeredCommands = await commands.getCommands(true)
await Promise.all(registeredCommands.map(async (eachRegisteredCommand) => {
if (eachRegisteredCommand === 'eslint.restart') {
await commands.executeCommand(eachRegisteredCommand)
}
}))
})
}

context.subscriptions.push(
commands.registerCommand('masterCSS.restart', restart),
client.onRequest('masterCSS/restart', restart),
workspace.onDidChangeConfiguration(async (event) => {
const affectedProperties = []
for (const optionName in settings) {
const property = `masterCSS.${optionName}`
if (event.affectsConfiguration(property)) {
affectedProperties.push(property)
const workspaceFolders = workspace.workspaceFolders ?? []
const affectedProperties: string[] = []
const shouldRestart = workspaceFolders?.some((folder) => {
for (const optionName in settings) {
const property = `masterCSS.${optionName}`
if (event.affectsConfiguration(property, folder)) {
affectedProperties.push(property)
return true
}
}
}
if (affectedProperties.length) {
return false
})
if (shouldRestart) {
window.withProgress({
location: ProgressLocation.Notification,
title: `Updating for "${affectedProperties}" ...`,
title: `Setting "${affectedProperties}"`,
}, async () => await client.restart())
commands.executeCommand('eslint.restart')
}
}),
)
Expand Down
2 changes: 1 addition & 1 deletion packages/vscode/src/server.min.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import CSSLanguageServer from '@master/css-language-server'

const server = new CSSLanguageServer()

server.connection.listen()
server.start()

process.on('unhandledRejection', (e) => {
console.error(`Unhandled rejection`, e)
Expand Down
9 changes: 6 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4b31640

Please sign in to comment.