file author sigmaliu
  import fs from 'fs' ; import path from 'path' ; import { CLIEngine } from 'eslint' ; import cluster from 'cluster' ; import { occurError , log , cwd , getAuthByEachLine , BOM , unknown , } from '../utils/utils' ; interface IMessage { column : number ; line : number ; message : string ; ruleId : string ; severity : number ; endColumn : number ; endLine ? : number ; fix ? : { range : [ number , number ] ; text : string ; } ; } const IS_DEMO = process . env . MODE === 'demo' ; const IS_VUE = process . env . TYPE === 'vue' ; export default class AutoFixAPI { param files public applyAutoFixToFiles = ( files ) => { try { const baseConfig = this . getBaseConfig ( ) ; const cli = new CLIEngine ( baseConfig ) ; const report = cli . executeOnFiles ( files ) ; const { errorCount , warningCount , fixableErrorCount , fixableWarningCount , } = report ; const infoCount = { errorCount , warningCount , fixableErrorCount , fixableWarningCount , } ; if ( cluster . isMaster ) { log ( JSON . stringify ( infoCount , null , 4 ) ) ; } else { process . send ! ( { infoCount } ) ; } CLIEngine . outputFixes ( report ) ; } catch ( err ) { occurError ( err ) ; } } ; param files public getESLintReportByAuth = ( files ) => { const baseConfig = this . getBaseConfig ( ) ; let [ fixableErrorCount , fixableWarningCount ] = [ 0 , 0 ] ; let [ totalErrorCount , totalWarningCount , totalFixableErrorCount , totalFixableWarningCount ] = [ 0 , 0 , 0 , 0 ] ; let messages = [ ] ; let lastFile = '' ; let currentFile = '' ; let authByEachLine = [ ] ; let sourceCode = '' ; let filterAuth = '' ; let bom = sourceCode . startsWith ( BOM ) ? BOM : '' ; sourceCode = bom ? sourceCode . slice ( 1 ) : sourceCode ; let lastPos = Number . NEGATIVE_INFINITY ; let output = bom ; param fix const attemptFix = ( fix ) => { const start = fix . range [ 0 ] ; const end = fix . range [ 1 ] ; if ( lastPos >= start || start > end ) { return false ; } if ( ( start < 0 && end >= 0 ) || ( start === 0 && fix . text . startsWith ( BOM ) ) ) { output = '' ; } output += sourceCode . slice ( Math . max ( 0 , lastPos ) , Math . max ( 0 , start ) ) ; output += fix . text ; lastPos = end ; sourceCode = output ; output = '' ; return true ; } ; baseConfig . fix = ( info ) => { messages . push ( info ) ; const { fix , line } = info ; if ( ! fix ) { return false ; } let shouldFix = false ; if ( lastFile !== currentFile ) { lastFile = currentFile ; authByEachLine = getAuthByEachLine ( currentFile ) ; sourceCode = fs . readFileSync ( currentFile , 'utf8' ) ; bom = sourceCode . startsWith ( BOM ) ? BOM : '' ; sourceCode = bom ? sourceCode . slice ( 1 ) : sourceCode ; lastPos = Number . NEGATIVE_INFINITY ; output = bom ; } const [ codeStart , codeEnd ] = fix . range ; const changedCode = sourceCode . slice ( codeStart , codeEnd ) ; const originLineCount = fix . text . split ( '\r?\n' ) . length ; const changeLineCount = changedCode . split ( '\r?\n' ) . length ; const changeAuth = authByEachLine [ line ] || unknown ; if ( originLineCount !== changeLineCount ) { authByEachLine . splice ( line , originLineCount , ... ( new Array ( changeLineCount ) . fill ( changeAuth ) ) ) ; } if ( ! filterAuth ) { filterAuth = changeAuth ; shouldFix = true ; } else if ( changeAuth === filterAuth ) { shouldFix = true ; } if ( shouldFix ) { shouldFix = attemptFix ( fix ) ; } if ( shouldFix ) { if ( info . severity === 2 ) { fixableErrorCount += 1 ; } else if ( info . severity === 1 ) { fixableWarningCount += 1 ; } } return shouldFix ; } ; const report = { results : [ ] , } ; const cli = new CLIEngine ( baseConfig ) ; for ( const file of files ) { currentFile = file ; messages = [ ] ; fixableErrorCount = 0 ; fixableWarningCount = 0 ; const result = cli . executeOnFiles ( [ file ] ) . results [ 0 ] ; result . messages = messages ; result . fixableErrorCount = fixableErrorCount ; result . fixableWarningCount = fixableWarningCount ; totalErrorCount += result . errorCount ; totalWarningCount += result . warningCount ; totalFixableErrorCount += fixableErrorCount ; totalFixableWarningCount += fixableWarningCount ; report . results . push ( result ) ; } report . errorCount = totalErrorCount ; report . warningCount = totalWarningCount ; report . fixableErrorCount = totalFixableErrorCount ; report . fixableWarningCount = totalFixableWarningCount ; return { report , auther : filterAuth , } ; } ; param report applyAutoFixByReport = ( report ) => { CLIEngine . outputFixes ( report ) ; } ; /**
     * 初始化
     */ private getBaseConfig = ( ) => { const ignoreFile = this . getFile ( '.eslintignore.json' , '.eslintignore' ) ; let config = this . getFile ( '.eslintrc.json' , '.eslintrc.js' ) ; if ( IS_DEMO && IS_VUE ) { config = this . getFile ( '.eslintrc-vue.json' ) ; } if ( ! config ) { occurError ( 'can not find .eslintrc.json or .eslintrc.js' ) ; } let ignoreConfig = { ignore : false , ignorePath : '' , } ; if ( ignoreFile && ! IS_DEMO ) { ignoreConfig = { ignore : true , ignorePath : ignoreFile , } ; } return { ... ignoreConfig , useEslintrc : true , configFile : config , fix : true , fixTypes : [ 'problem' , 'suggestion' , 'layout' ] , rules : { '@typescript-eslint/prefer-string-starts-ends-with' : 0 , '@typescript-eslint/no-non-null-assertion' : 0 , '@typescript-eslint/no-unnecessary-type-assertion' : 0 , } , } ; } ; param prefer param backup private getFile = ( prefer , backup = '' ) => { const prePath = path . resolve ( cwd , prefer ) ; const backPath = path . resolve ( cwd , backup ) ; if ( fs . existsSync ( prePath ) ) { return prePath ; } if ( backup && fs . existsSync ( backPath ) ) { return backPath ; } return null ; } ; }