Skip to content

Commit

Permalink
feat: support qmlls
Browse files Browse the repository at this point in the history
  • Loading branch information
seanwu1105 committed Jan 28, 2023
1 parent a98c773 commit 6dddd3c
Show file tree
Hide file tree
Showing 16 changed files with 345 additions and 37 deletions.
91 changes: 71 additions & 20 deletions package-lock.json

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

22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"prepare": "husky install"
},
"dependencies": {
"vscode-languageclient": "^8.0.2",
"vscode-uri": "^3.0.3",
"zod": "^3.20.2"
},
Expand Down Expand Up @@ -238,6 +239,27 @@
"markdownDescription": "The options passed to Qt `qmllint` executable. See [here](https://github.com/seanwu1105/vscode-qt-for-python#predefined-variables) for a detailed list of predefined variables.",
"scope": "resource"
},
"qtForPython.qmlls.enabled": {
"type": "boolean",
"default": true,
"markdownDescription": "Enable the Qt `qmlls` integration.",
"scope": "window"
},
"qtForPython.qmlls.path": {
"type": "string",
"default": "",
"markdownDescription": "The path to Qt `qmlls` executable. Set to empty string to automatically resolve from the installed Python package. See [here](https://github.com/seanwu1105/vscode-qt-for-python#predefined-variables) for a detailed list of predefined variables.",
"scope": "window"
},
"qtForPython.qmlls.options": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"markdownDescription": "The options passed to Qt `qmlls` executable. See [here](https://github.com/seanwu1105/vscode-qt-for-python#predefined-variables) for a detailed list of predefined variables.",
"scope": "window"
},
"qtForPython.rcc.path": {
"type": "string",
"default": "",
Expand Down
1 change: 1 addition & 0 deletions python/.coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
omit =
**/test_*.py
scripts/qmllint.py
scripts/qmlls.py
scripts/rcc.py
scripts/uic.py
scripts/designer.py
Expand Down
14 changes: 14 additions & 0 deletions python/scripts/qmlls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# pylint: disable=import-error

import re
import sys

from utils import is_installed

if __name__ == "__main__":
if is_installed("PySide6"):
from PySide6.scripts.pyside_tool import qmlls
else:
sys.exit("No qmlls can be found in current Python environment.")
sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0])
sys.exit(qmlls())
17 changes: 17 additions & 0 deletions python/tests/test_qmlls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import subprocess

from tests import SCRIPTS_DIR


def test_qmlls_help():
result = invoke_qmlls_py(["--help"])
assert result.returncode == 0
assert len(result.stdout.decode("utf-8")) > 0


def invoke_qmlls_py(args: list[str]):
return subprocess.run(
["poetry", "run", "python", "qmlls.py", *args],
cwd=SCRIPTS_DIR,
capture_output=True,
)
4 changes: 2 additions & 2 deletions src/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function getPathFromConfig({ tool, resource }: GetPathFromConfig) {

type GetPathFromConfig = {
readonly tool: SupportedTool
readonly resource: URI
readonly resource: URI | undefined
}

export function getOptionsFromConfig({
Expand All @@ -36,5 +36,5 @@ export function getOptionsFromConfig({

type GetOptionsFromConfig = {
readonly tool: SupportedTool
readonly resource: URI
readonly resource: URI | undefined
}
29 changes: 27 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { commands, window } from 'vscode'
import { COMMANDS } from './commands'
import { EXTENSION_NAMESPACE } from './constants'
import { registerQmlLint } from './qmllint/register'
import { registerQmlLanguageServer } from './qmlls/client'
import type { ExecError, StdErrError } from './run'
import type { ErrorResult, SuccessResult } from './types'
import { registerUicLiveExecution } from './uic/uic-live-execution'
Expand All @@ -25,6 +26,13 @@ export async function activate(context: ExtensionContext) {
extensionPath: context.extensionPath,
onResult: onResultReceived,
})

registerQmlLanguageServer({
subscriptions: context.subscriptions,
extensionPath: context.extensionPath,
outputChannel,
onResult: onResultReceived,
})
}

function registerCommands({ extensionPath, subscriptions }: ExtensionContext) {
Expand Down Expand Up @@ -64,7 +72,10 @@ function onResultReceived(
switch (result.kind) {
case 'Success':
return outputChannel.appendLine(
JSON.stringify(result.value, null, indent),
prefixLogging({
message: JSON.stringify(result.value, null, indent),
severity: 'INFO',
}),
)
case 'ParseError':
case 'TypeError':
Expand All @@ -81,6 +92,20 @@ function onResultReceived(
}

async function showError(message: string) {
outputChannel.appendLine(message)
outputChannel.appendLine(prefixLogging({ message, severity: 'ERROR' }))
return window.showErrorMessage(message)
}

function prefixLogging({ message, severity }: PrefixLoggingArgs) {
return `[${severity.padEnd(
Math.max(...LoggingSeverity.map(s => s.length)),
)} - ${new Date().toLocaleTimeString()}] ${message}`
}

type PrefixLoggingArgs = {
readonly message: string
readonly severity: LoggingSeverity
}

const LoggingSeverity = ['INFO', 'ERROR'] as const
type LoggingSeverity = typeof LoggingSeverity[number]
12 changes: 7 additions & 5 deletions src/predefined-variable-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as os from 'node:os'
import * as path from 'node:path'
import { env, window, workspace } from 'vscode'
import type { URI } from 'vscode-uri'
import { notNil } from './utils'
import { isNil, notNil } from './utils'

export function resolvePredefinedVariables({
str,
Expand All @@ -26,10 +26,10 @@ export function resolvePredefinedVariables({

type ResolvePredefinedVariablesArgs = {
readonly str: string
readonly resource: URI
readonly resource: URI | undefined
}

function getResolver(resource: URI) {
function getResolver(resource: URI | undefined) {
return {
userHome: () => os.homedir(),

Expand Down Expand Up @@ -86,10 +86,12 @@ function getResolver(resource: URI) {

// -- Additional Variables --

resource: () => resource.fsPath,
resource: () => resource?.fsPath ?? '',

resourceWorkspaceFolder: () =>
workspace.getWorkspaceFolder(resource)?.uri.fsPath ?? '',
isNil(resource)
? ''
: workspace.getWorkspaceFolder(resource)?.uri.fsPath ?? '',

relativeResource: () =>
path.relative(
Expand Down
Loading

0 comments on commit 6dddd3c

Please sign in to comment.