Skip to content

Commit

Permalink
feat: support diagnostic summary for ESLint & VLS
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Feb 12, 2022
1 parent 0a7a1e7 commit 904d49d
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 35 deletions.
4 changes: 4 additions & 0 deletions packages/vite-plugin-checker/src/checkers/eslint/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
filterLogLevel,
normalizeEslintDiagnostic,
toViteCustomPayload,
composeCheckerSummary,
} from '../../logger'
import { ACTION_TYPES, DiagnosticLevel } from '../../types'
import { translateOptions } from './cli'
Expand Down Expand Up @@ -62,6 +63,9 @@ const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => {
diagnostics.forEach((d) => {
consoleLog(diagnosticToTerminalLog(d, 'ESLint'))
})
const errorCount = diagnostics.filter((d) => d.level === DiagnosticLevel.Error).length
const warningCount = diagnostics.filter((d) => d.level === DiagnosticLevel.Warning).length
consoleLog(composeCheckerSummary('ESLint', errorCount, warningCount))
}

if (overlay) {
Expand Down
4 changes: 3 additions & 1 deletion packages/vite-plugin-checker/src/checkers/typescript/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ensureCall,
normalizeTsDiagnostic,
toViteCustomPayload,
composeCheckerSummary,
} from '../../logger'
import { ACTION_TYPES, CreateDiagnostic, DiagnosticLevel, DiagnosticToRuntime } from '../../types'

Expand Down Expand Up @@ -92,7 +93,8 @@ const createDiagnostic: CreateDiagnostic<'typescript'> = (pluginConfig) => {
}

if (terminal) {
consoleLog(logChunk + os.EOL + diagnostic.messageText.toString())
consoleLog(logChunk)
consoleLog(composeCheckerSummary('TypeScript', 1, 2))
}
})
}
Expand Down
49 changes: 31 additions & 18 deletions packages/vite-plugin-checker/src/checkers/vls/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export type LogLevel = typeof logLevels[number]
export const logLevels = ['ERROR', 'WARN', 'INFO', 'HINT'] as const

let disposeSuppressConsole: ReturnType<typeof suppressConsole>
let initialVueFilesCount = 0
let initialVueFilesTick = 0
const fileDiagnosticManager = new FileDiagnosticManager()

export const logLevel2Severity = {
Expand All @@ -57,16 +59,16 @@ export interface DiagnosticOptions {
watch: boolean
verbose: boolean
config: DeepPartial<VlsOptions> | null
onDispatch?: (normalized: NormalizedDiagnostic[]) => void
onDispatchInitialSummary?: (errorCount: number) => void
onDispatchDiagnostics?: (normalized: NormalizedDiagnostic[]) => void
onDispatchDiagnosticsSummary?: (errorCount: number, warningCount: number) => void
}

export async function diagnostics(
workspace: string | null,
logLevel: LogLevel,
options: DiagnosticOptions = { watch: false, verbose: false, config: null }
) {
const { watch, onDispatch } = options
const { watch, onDispatchDiagnostics: onDispatch } = options
if (options.verbose) {
console.log('====================================')
console.log('Getting Vetur diagnostics')
Expand All @@ -82,16 +84,17 @@ export async function diagnostics(
workspaceUri = URI.file(process.cwd())
}

const errCount = await getDiagnostics(workspaceUri, logLevel2Severity[logLevel], options)
const result = await getDiagnostics(workspaceUri, logLevel2Severity[logLevel], options)

if (options.verbose) {
console.log('====================================')
}

// dispatch error summary in build mode
if (!options.watch && typeof errCount === 'number') {
options?.onDispatchInitialSummary?.(errCount)
process.exit(errCount > 0 ? 1 : 0)
if (!options.watch && typeof result === 'object' && result !== null) {
const { initialErrorCount, initialWarningCount } = result
options?.onDispatchDiagnosticsSummary?.(initialErrorCount, initialWarningCount)
process.exit(initialErrorCount > 0 ? 1 : 0)
}
}

Expand Down Expand Up @@ -155,7 +158,14 @@ export async function prepareClientConnection(
fileDiagnosticManager.updateByFileId(absFilePath, nextDiagnosticInFile)

const normalized = fileDiagnosticManager.getDiagnostics()
options.onDispatch?.(normalized)
const errorCount = normalized.filter((d) => d.level === DiagnosticSeverity.Error).length
const warningCount = normalized.filter((d) => d.level === DiagnosticSeverity.Warning).length
initialVueFilesTick++
options.onDispatchDiagnostics?.(normalized)
// only starts to log summary when all .vue files are loaded
if (initialVueFilesTick >= initialVueFilesCount) {
options.onDispatchDiagnosticsSummary?.(errorCount, warningCount)
}
}

const vls = new VLS(serverConnection as any)
Expand Down Expand Up @@ -207,23 +217,22 @@ function extToGlobs(exts: string[]) {
const watchedDidChangeContent = ['.vue']
const watchedDidChangeWatchedFiles = ['.js', '.ts', '.json']
const watchedDidChangeContentGlob = extToGlobs(watchedDidChangeContent)
const watchedDidChangeWatchedFilesGlob = extToGlobs(watchedDidChangeWatchedFiles)

async function getDiagnostics(
workspaceUri: URI,
severity: DiagnosticSeverity,
options: DiagnosticOptions
): Promise<number | null> {
): Promise<{ initialErrorCount: number; initialWarningCount: number } | null> {
const { clientConnection } = await prepareClientConnection(workspaceUri, severity, options)

const files = glob.sync([...watchedDidChangeContentGlob, ...watchedDidChangeWatchedFilesGlob], {
const files = glob.sync([...watchedDidChangeContentGlob], {
cwd: workspaceUri.fsPath,
ignore: ['node_modules/**'],
})

if (files.length === 0) {
console.log('[VLS checker] No input files')
return 0
return { initialWarningCount: 0, initialErrorCount: 0 }
}

if (options.verbose) {
Expand All @@ -235,8 +244,9 @@ async function getDiagnostics(

// VLS will stdout verbose log, suppress console before any serverConnection
disposeSuppressConsole = suppressConsole()

let initialErrCount = 0
initialVueFilesCount = absFilePaths.length
let initialErrorCount = 0
let initialWarningCount = 0
await Promise.all(
absFilePaths.map(async (absFilePath) => {
// serve mode - step 1
Expand Down Expand Up @@ -281,23 +291,26 @@ async function getDiagnostics(

diagnostics.forEach((d) => {
if (d.severity === DiagnosticSeverity.Error) {
initialErrCount++
initialErrorCount++
}
if (d.severity === DiagnosticSeverity.Warning) {
initialWarningCount++
}
})
}

console.log(logChunk)
return initialErrCount
return { initialErrorCount, initialWarningCount }
} catch (err) {
console.error(err.stack)
return initialErrCount
return { initialErrorCount, initialWarningCount }
}
}
})
)

if (!options.watch) {
return initialErrCount
return { initialErrorCount, initialWarningCount }
}

// serve mode - step 2
Expand Down
38 changes: 22 additions & 16 deletions packages/vite-plugin-checker/src/checkers/vls/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { parentPort } from 'worker_threads'

import { Checker } from '../../Checker'
import {
composeCheckerSummary,
consoleLog,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
toViteCustomPayload,
} from '../../logger'
import { ACTION_TYPES } from '../../types'
import { ACTION_TYPES, DiagnosticLevel } from '../../types'
import { DiagnosticOptions, diagnostics } from './diagnostics'

import type { ConfigEnv } from 'vite'
Expand All @@ -29,7 +30,24 @@ export const createDiagnostic: CreateDiagnostic<'vls'> = (pluginConfig) => {
async configureServer({ root }) {
const workDir: string = root

const onDispatch: DiagnosticOptions['onDispatch'] = (normalized) => {
const onDispatchDiagnosticsSummary: DiagnosticOptions['onDispatchDiagnosticsSummary'] = (
errorCount,
warningCount
) => {
if (!terminal) return

consoleLog(composeCheckerSummary('VLS', errorCount, warningCount))

// if (!errorCount) {
// consoleLog(chalk.green(`[VLS checker] No error found`))
// } else {
// consoleLog(
// chalk.red(`[VLS checker] Found ${errorCount} ${errorCount === 1 ? 'error' : 'errors'}`)
// )
// }
}

const onDispatchDiagnostics: DiagnosticOptions['onDispatchDiagnostics'] = (normalized) => {
if (overlay && command === 'serve') {
parentPort?.postMessage({
type: ACTION_TYPES.overlayError,
Expand All @@ -42,22 +60,10 @@ export const createDiagnostic: CreateDiagnostic<'vls'> = (pluginConfig) => {
}
}

const onDispatchInitialSummary: DiagnosticOptions['onDispatchInitialSummary'] = (
errCount
) => {
if (!errCount) {
consoleLog(chalk.green(`[VLS checker] No error found`))
} else {
consoleLog(
chalk.red(`[VLS checker] Found ${errCount} ${errCount === 1 ? 'error' : 'errors'}`)
)
}
}

const vlsConfig = pluginConfig?.vls
await diagnostics(workDir, 'WARN', {
onDispatch,
onDispatchInitialSummary,
onDispatchDiagnostics,
onDispatchDiagnosticsSummary,
watch: true,
verbose: false,
config: typeof vlsConfig === 'object' ? vlsConfig : null,
Expand Down
19 changes: 19 additions & 0 deletions packages/vite-plugin-checker/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,25 @@ export function tsLocationToBabelLocation(
}
}

export function wrapCheckerSummary(checkerName: string, rawSummary: string): string {
return `[${checkerName}] ${rawSummary}`
}

export function composeCheckerSummary(
checkerName: string,
errorCount: number,
warningCount: number
): string {
const message = `Found ${errorCount} error${
errorCount > 1 ? 's' : ''
} and ${warningCount} warning${warningCount > 1 ? 's' : ''}`

const hasError = errorCount > 0
const hasWarning = warningCount > 0
const color = hasError ? 'red' : hasWarning ? 'yellow' : 'green'
return chalk[color](wrapCheckerSummary(checkerName, message))
}

/* ------------------------------- TypeScript ------------------------------- */

export function normalizeTsDiagnostic(d: TsDiagnostic): NormalizedDiagnostic {
Expand Down

0 comments on commit 904d49d

Please sign in to comment.