nitro-codegen
Version:
The code-generator for react-native-nitro-modules.
117 lines (102 loc) • 3.31 kB
text/typescript
import type { SourceFile } from './syntax/SourceFile.js'
import path from 'path'
import type { SwiftCxxHelper } from './syntax/swift/SwiftCxxTypeHelper.js'
import type { Type } from 'ts-morph'
import { isNotDuplicate } from './syntax/helpers.js'
export function capitalizeName(name: string): string {
if (name.length === 0) return name
return name.charAt(0).toUpperCase() + name.slice(1)
}
export function createIndentation(spacesCount: number): string {
return Array.from(Array(spacesCount)).fill(' ').join('')
}
export function indent(string: string, spacesCount: number): string
export function indent(string: string, indentation: string): string
export function indent(string: string, indentation: string | number): string {
let spaces: string
if (typeof indentation === 'number') {
spaces = createIndentation(indentation)
} else {
spaces = indentation
}
return string.replaceAll('\n', `\n${spaces}`)
}
export function errorToString(error: unknown): string {
if (error == null) {
return `null`
}
if (typeof error !== 'object') {
return `${error}`
}
if (error instanceof Error) {
let message = `${error.name}: ${error.message}`
if (error.cause != null) {
message += ` (cause: ${JSON.stringify(error.cause)})`
}
return message
}
if ('toString' in error) {
return error.toString()
}
return JSON.stringify(error)
}
export function escapeComments(string: string): string {
return string
.replace(/\/\*/g, '/ *') // Escape start of comment
.replace(/\*\//g, '* /') // Escape end of comment
.replace(/\/\//g, '/ /') // Escape single-line comment
}
const HAS_UNIX_PATHS = path.join('a', 'b').includes('/')
export function toUnixPath(p: string): string {
if (HAS_UNIX_PATHS) return p
return p.replaceAll('\\', '/')
}
function getFullPath(file: SourceFile): string {
return path.join(
file.platform,
file.language,
...file.subdirectory,
file.content
)
}
export function filterDuplicateFiles(
f: SourceFile,
i: number,
array: SourceFile[]
): boolean {
const otherIndex = array.findIndex((f2) => getFullPath(f) === getFullPath(f2))
if (otherIndex !== i) {
if (array[i]?.content !== array[otherIndex]?.content) {
throw new Error(`File "${f.name}"'s content differs!`)
}
}
return otherIndex === i
}
export function filterDuplicateHelperBridges(
bridge: SwiftCxxHelper,
i: number,
array: SwiftCxxHelper[]
): boolean {
const otherIndex = array.findIndex(
(f2) => bridge.specializationName === f2.specializationName
)
return otherIndex === i
}
export function toLowerCamelCase(string: string): string {
const parts = string.split('_').filter((part) => part !== '')
if (parts.length === 0) return ''
const camelCaseString = parts[0]!.toLowerCase()
const camelCased = parts
.slice(1)
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
return camelCaseString + camelCased.join('')
}
export function getBaseTypes(type: Type): Type[] {
const baseTypes = type.getBaseTypes()
const symbol = type.getSymbol()
if (symbol != null) {
baseTypes.push(...symbol.getDeclaredType().getBaseTypes())
}
const recursive = baseTypes.flatMap((b) => [b, ...getBaseTypes(b)])
return recursive.filter(isNotDuplicate)
}