import * as fs from 'fs' ; import { EOL } from 'os' ; import { workspace , window } from 'vscode' ; import { CsvStructure } from './model' ; import { getCsvFileHeader , getCsvFileLinesAsIterable , setCsvFileContent } from './utils/storage-utils' ; import { getBackupFilename , toAbsolutePath } from './utils/workspace-util' ; /**
 * Code review file check operations
 */ export enum CheckFlag { /** Check the format of the file */ format = 0x1 , /** Try to migrate the format of the file */ migrate = 0x2 } export class FileGenerator { private readonly defaultFileExtension = '.csv' ; private defaultFileName = 'code-review' ; constructor ( private workspaceRoot ) { const configFileName = workspace . getConfiguration ( ) . get ( 'code-review.filename' ) as string ; if ( configFileName ) { this . defaultFileName = configFileName ; } } public get reviewFileName ( ) : string { return `${ this . defaultFileName }${ this . defaultFileExtension }` ; } public get reviewFilePath ( ) : string { return toAbsolutePath ( this . workspaceRoot , this . reviewFileName ) ; } return public create ( ) { if ( fs . existsSync ( this . reviewFilePath ) ) { if ( ! this . check ( ) ) { return false ; } } else { try { fs . writeFileSync ( this . reviewFilePath , `${ CsvStructure . headerLine }${ EOL }` ) ; window . showInformationMessage ( `Code review file: '${ this . defaultFileName }${ this . defaultFileExtension }' successfully created.` ) ; } catch ( err ) { window . showErrorMessage ( `Error when trying to create code review file: '${ this . reviewFilePath }': ${ err }` ) ; return false ; } } return true ; } param flags return public check ( flags = CheckFlag . format ) { if ( ! fs . existsSync ( this . reviewFilePath ) ) { return true ; } let result = true ; if ( flags & CheckFlag . format ) { result = this . checkFormat ( ) ; } if ( ! result && flags & CheckFlag . migrate ) { result = this . migrate ( ) ; } return result ; } private checkFormat ( ) { const currentHeader = getCsvFileHeader ( this . reviewFilePath ) ; return currentHeader === CsvStructure . headerLine ; } return private migrate ( ) { const currentHeader = getCsvFileHeader ( this . reviewFilePath ) ; if ( currentHeader === CsvStructure . headerLine ) { return true ; } if ( ! CsvStructure . headerLine . startsWith ( currentHeader ) ) { window . showErrorMessage ( `CSV header "${ currentHeader ?? '' }" is not matching "${ CsvStructure . headerLine }" format. Please adjust it manually` ) ; return false ; } const missingHeaders = CsvStructure . headerLine . substring ( currentHeader . length + 1 ) . split ( CsvStructure . separator ) ; let fileContent = '' ; let isHeader = true ; for ( const line of getCsvFileLinesAsIterable ( this . reviewFilePath ) ) { if ( isHeader ) { fileContent += line + CsvStructure . separator + missingHeaders . join ( CsvStructure . separator ) ; isHeader = false ; } else { fileContent += line ; for ( const column of missingHeaders ) { fileContent += `${ CsvStructure . separator }"${ CsvStructure . getDefaultValue ( column ) ?? '' }"` ; } } fileContent += EOL ; } fs . renameSync ( this . reviewFilePath , getBackupFilename ( this . reviewFilePath ) ) ; if ( ! setCsvFileContent ( this . reviewFilePath , fileContent ) ) { window . showErrorMessage ( `Error in writing new content to the file "${ this . reviewFilePath }".` ) ; return false ; } return true ; } /**
     * not really using anything that needs to be disposed of, but
     * including in case we need to use in a future update
     */ dispose ( ) { } }