import { UniqueNameGenerator , camelCase , unique } from '@sap-cloud-sdk/util' ; import { ParserOptions } from './options' ; param names param options param namingOptions param options . format param options . reservedWords param options . separator returns internal export function ensureUniqueNames ( names , options , namingOptions ? ) { const { format = camelCase , reservedWords = [ ] , separator = '' } = namingOptions || { } ; if ( options . strictNaming ) { const formattedNames = names . map ( originalName => format ( originalName ) ) ; validateUniqueness ( names , formattedNames , reservedWords ) ; return formattedNames ; } return deduplicateNames ( names , { format , reservedWords , separator } ) ; } param names param formattedNames param reservedWords internal export function validateUniqueness ( names , formattedNames , reservedWords = [ ] ) { if ( hasDuplicates ( formattedNames ) || hasReservedWords ( formattedNames , reservedWords ) ) { throw new Error ( getDuplicateErrorMessage ( names , formattedNames , reservedWords ) ) ; } } param names param namingOptions param namingOptions . format param namingOptions . reservedWords returns internal export function deduplicateNames ( names , namingOptions ? ) { const { format = camelCase , reservedWords = [ ] , separator = '' } = namingOptions || { } ; const nonConflictingNames = getNonConflictingNames ( names , format , reservedWords ) ; const nameGenerator = new UniqueNameGenerator ( separator , [ ... reservedWords , ... nonConflictingNames ] ) ; return names . map ( name => { if ( nonConflictingNames . length && nonConflictingNames [ 0 ] === name ) { nonConflictingNames . shift ( ) ; return name ; } return nameGenerator . generateAndSaveUniqueName ( format ( name ) ) ; } , { } ) ; } param names param format param reservedWords returns function getNonConflictingNames ( names , format , reservedWords ) { return names . reduce ( ( correctNames , name ) => isReserved ( name , reservedWords ) || isDuplicate ( name , correctNames ) || ! isFormatted ( name , format ) ? correctNames : [ ... correctNames , name ] , [ ] ) ; } function isReserved ( name , reservedWords ) { return reservedWords . includes ( name ) ; } function isDuplicate ( name , correctNames ) { return correctNames . some ( correctName => correctName === name ) ; } function isFormatted ( name , format ) { return format ( name ) === name ; } function hasDuplicates ( names ) { const uniqueNames = unique ( names ) ; return uniqueNames . length !== names . length ; } function hasReservedWords ( names , reservedWords ) { return ! ! reservedWords . find ( reservedWord => names . includes ( reservedWord ) ) ; } function getDuplicateErrorMessage ( names , formattedNames , reservedWords ) { const uniqueNames = unique ( formattedNames ) ; let errorMessage = '' ; if ( hasDuplicates ( formattedNames ) ) { errorMessage += `Some names are not unique after formatting.\n${ getDuplicateErrorLines ( names , formattedNames , uniqueNames , 1 ) }` ; } if ( hasReservedWords ( formattedNames , reservedWords ) ) { errorMessage += `Some names are reserved words after formatting.\n${ getDuplicateErrorLines ( names , formattedNames , reservedWords , 0 ) }` ; } return errorMessage ; } param originalNames param formattedNames param uniqueNames param threshold returns function getDuplicateErrorLines ( originalNames , formattedNames , uniqueNames , threshold ) { const duplicatesByName = uniqueNames . reduce ( ( duplicates , formattedName ) => { const duplicateNames = originalNames . filter ( ( _ , i ) => formattedNames [ i ] === formattedName ) ; return duplicateNames . length > threshold ? { ... duplicates , [ formattedName ] : duplicateNames } : duplicates ; } , { } ) ; return Object . entries ( duplicatesByName ) . map ( ( [ formattedName , duplicateNames ] ) => `\tFormatted name: '${ formattedName }', original names: ${ duplicateNames . map ( duplicate => `'${ duplicate }'` ) . join ( ', ' ) }.` ) . join ( '\n' ) ; }