Skip to content

Commit

Permalink
Fix #85 - add support for passing configuration to VLS.
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/vite-plugin-checker/src/checkers/vls/main.ts
#	packages/vite-plugin-checker/src/types.ts
  • Loading branch information
ascott18 authored and fi3ework committed Feb 6, 2022
1 parent 820676d commit afd5b9b
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 16 deletions.
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,26 @@ export default {

### config.vls

_coming soon._
VLS configuration accepts the same values that can be configured in VS code with keys that start with `vetur`.
These are configured with nested objects rather than dotted string notation. Typescript intellisense is available.

| field | Type | Default value | Description |
| :---- | ---- | ------------- | ----------- |
| | | | |
See [`initParams.ts`](https://github.com/fi3ework/vite-plugin-checker/blob/8fc5d7f4a908a4c80d1cb978e0acf1d4e5700e6a/packages/vite-plugin-checker/src/checkers/vls/initParams.ts#L33) for a comprehensive list of the defaults that can be overridden. Vetur unfortunately does not provide a single comprehensive document of all its options.

For example, to performing checking only the `<script>` block:
```ts
checker({
vls: {
vetur: {
validation: {
template: false,
templateProps: false,
interpolation: false,
style: false,
},
},
},
}),
```

### config.vueTsc

Expand Down
13 changes: 12 additions & 1 deletion packages/vite-plugin-checker/src/checkers/vls/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ function validateLogLevel(logLevelInput: unknown): logLevelInput is LogLevel {
program
.command('diagnostics [workspace]')
.description('Print all diagnostics')
.addOption(
new Option('-c, --checker-config <checkerConfig>', 'Option overrides to pass to VTI')
.default('{}')
)
.addOption(
new Option('-l, --log-level <logLevel>', 'Log level to print')
.default('WARN')
Expand All @@ -35,7 +39,14 @@ function validateLogLevel(logLevelInput: unknown): logLevelInput is LogLevel {
throw new Error(`Invalid log level: ${logLevelOption}`)
}

await diagnostics(workspace, logLevelOption)
let parsedConfig;
try {
parsedConfig = JSON.parse(options.checkerConfig) as any
} catch {
throw new Error(`Unable to parse checker-config JSON: ${options.checkerConfig}`)
}

await diagnostics(workspace, logLevelOption, { watch: false, verbose: false, config: parsedConfig })
})

program.parse(process.argv)
Expand Down
31 changes: 29 additions & 2 deletions packages/vite-plugin-checker/src/checkers/vls/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ import {
normalizeLspDiagnostic,
normalizePublishDiagnosticParams,
} from '../../logger'
import { getInitParams } from './initParams'
import { getInitParams, VlsOptions } from './initParams'

import type { ErrorPayload } from 'vite'
import { DeepPartial } from '../../types'

enum DOC_VERSION {
init = -1,
Expand All @@ -55,13 +56,14 @@ const logLevel2Severity = {
export interface DiagnosticOptions {
watch: boolean
verbose: boolean
config: DeepPartial<VlsOptions> | null
errorCallback?: (diagnostic: PublishDiagnosticsParams, viteError: ErrorPayload['err']) => void
}

export async function diagnostics(
workspace: string | null,
logLevel: LogLevel,
options: DiagnosticOptions = { watch: false, verbose: false }
options: DiagnosticOptions = { watch: false, verbose: false, config: null }
) {
const { watch, errorCallback } = options
if (options.verbose) {
Expand Down Expand Up @@ -200,6 +202,11 @@ async function prepareClientConnection(workspaceUri: URI, options: DiagnosticOpt

const init = getInitParams(workspaceUri)

if (options.config) {
// Merge in used-provided VLS settings if present
mergeDeep(init.initializationOptions.config, options.config);
}

await clientConnection.sendRequest(InitializeRequest.type, init)

return clientConnection
Expand Down Expand Up @@ -315,3 +322,23 @@ async function getDiagnostics(
consoleLogVls(logChunk)
return initialErrCount
}


function isObject(item: any): item is {} {
return item && typeof item === 'object' && !Array.isArray(item);
}

function mergeDeep<T>(target: T, source: DeepPartial<T> | undefined) {
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
mergeDeep(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}

return target;
}
2 changes: 2 additions & 0 deletions packages/vite-plugin-checker/src/checkers/vls/initParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { URI } from 'vscode-uri'

import type { InitializeParams } from 'vscode-languageserver/node'

export type VlsOptions = ReturnType<typeof getDefaultVLSConfig>;

export function getInitParams(workspaceUri: URI): InitializeParams {
const defaultVLSConfig = getDefaultVLSConfig()

Expand Down
29 changes: 26 additions & 3 deletions packages/vite-plugin-checker/src/checkers/vls/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parentPort } from 'worker_threads'
import { parentPort, workerData } from 'worker_threads'

import { Checker } from '../../Checker'
import { ACTION_TYPES } from '../../types'
Expand Down Expand Up @@ -30,7 +30,14 @@ export const createDiagnostic: CreateDiagnostic<'vls'> = (pluginConfig) => {
: null,
})
}
await diagnostics(workDir, 'WARN', { watch: true, errorCallback, verbose: false })

const vlsConfig = workerData?.checkerConfig?.vls
await diagnostics(workDir, 'WARN', {
errorCallback,
watch: true,
verbose: false,
config: typeof vlsConfig === 'object' ? vlsConfig : undefined,
})
},
}
}
Expand All @@ -40,7 +47,23 @@ export class VlsChecker extends Checker<'vls'> {
super({
name: 'vls',
absFilePath: __filename,
build: { buildBin: ['vite-plugin-checker-vls', ['diagnostics']] },
build: {
buildBin: (config) => {
if (typeof config.vls === 'object') {
return [
'vite-plugin-checker-vls',
[
'diagnostics',
'--checker-config',
// Escape quotes so that the system shell doesn't strip them out:
'"' + JSON.stringify(config.vls).replace(/[\\"]/g, '\\$&') + '"',
],
]
}

return ['vite-plugin-checker-vls', ['diagnostics']]
},
},
createDiagnostic,
})
}
Expand Down
8 changes: 7 additions & 1 deletion packages/vite-plugin-checker/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,13 @@ function spawnChecker(
cwd: process.cwd(),
stdio: 'inherit',
env: localEnv,
shell: os.platform() === 'win32',
// shell is necessary on windows to get the process to even start.
// Command line args constructed by checkers therefore need to escape double quotes
// to have them not striped out by cmd.exe. Using shell on all platforms lets us avoid
// having to perform platform-specific logic around escaping quotes since all platform
// shells will strip out unescaped double quotes. shell=false on linux would result
// on escaped quotes not being unescaped.
shell: true,
})

proc.on('exit', (code) => {
Expand Down
13 changes: 8 additions & 5 deletions packages/vite-plugin-checker/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { HMRPayload, ServerOptions, ConfigEnv } from 'vite'
import type { Worker } from 'worker_threads'
import type { ESLint } from 'eslint'
import type { VlsOptions } from './checkers/vls/initParams'

/* ----------------------------- userland plugin options ----------------------------- */

Expand All @@ -24,11 +25,7 @@ export type VueTscConfig =
}>

/** vls checker configuration */
export type VlsConfig =
| boolean
| Partial<{
// TODO: support vls config
}>
export type VlsConfig = boolean | DeepPartial<VlsOptions>

/** ESLint checker configuration */
export type EslintConfig =
Expand Down Expand Up @@ -179,3 +176,9 @@ export interface CheckerDiagnostic {
export type CreateDiagnostic<T extends BuildInCheckerNames = any> = (
config: Pick<BuildInCheckers, T> & SharedConfig
) => CheckerDiagnostic

/* ----------------------------- generic utility types ----------------------------- */

export type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>
}

0 comments on commit afd5b9b

Please sign in to comment.