2023-10-16 19:23:53 +03:00
|
|
|
import { TlArgument, TlArgumentDiff, TlEntry, TlEntryDiff, TlFullSchema, TlSchemaDiff } from './types.js'
|
|
|
|
import { stringifyArgumentType } from './utils.js'
|
2021-11-23 00:03:59 +03:00
|
|
|
|
2022-08-29 14:33:11 +03:00
|
|
|
/**
|
|
|
|
* Compute difference between two TL entries.
|
|
|
|
*
|
|
|
|
* @param a Entry A (field `old` in diff)
|
|
|
|
* @param b Entry B (field `new` in diff)
|
|
|
|
*/
|
2023-09-24 01:32:22 +03:00
|
|
|
export function generateTlEntriesDifference(a: TlEntry, b: TlEntry): TlEntryDiff {
|
2021-11-23 00:03:59 +03:00
|
|
|
if (a.kind !== b.kind || a.name !== b.name) {
|
|
|
|
throw new Error('Incompatible entries')
|
|
|
|
}
|
|
|
|
|
|
|
|
const diff: TlEntryDiff = {
|
|
|
|
name: a.name,
|
|
|
|
}
|
|
|
|
|
2022-06-30 16:32:56 +03:00
|
|
|
if (a.comment !== b.comment) {
|
|
|
|
diff.comment = {
|
|
|
|
old: a.comment,
|
|
|
|
new: b.comment,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
if (a.id !== b.id) {
|
2023-11-09 21:03:52 +03:00
|
|
|
const oldId = a.id
|
|
|
|
const newId = b.id
|
2021-11-23 00:03:59 +03:00
|
|
|
|
2023-11-09 21:03:52 +03:00
|
|
|
/* c8 ignore next 3 */
|
|
|
|
if (oldId === 0 || newId === 0) {
|
|
|
|
throw new Error('Entry ID cannot be 0')
|
|
|
|
}
|
2021-11-23 00:03:59 +03:00
|
|
|
|
|
|
|
if (oldId !== newId) {
|
|
|
|
diff.id = {
|
|
|
|
old: oldId,
|
|
|
|
new: newId,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
!a.generics !== !b.generics ||
|
2023-09-24 01:32:22 +03:00
|
|
|
(a.generics && b.generics && JSON.stringify(a.generics) !== JSON.stringify(b.generics))
|
2021-11-23 00:03:59 +03:00
|
|
|
) {
|
|
|
|
diff.generics = {
|
|
|
|
old: a.generics,
|
|
|
|
new: b.generics,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const argsDiff: NonNullable<TlEntryDiff['arguments']> = {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
}
|
|
|
|
|
|
|
|
const oldArgsIndex: Record<string, TlArgument> = {}
|
|
|
|
|
|
|
|
a.arguments.forEach((arg) => {
|
|
|
|
oldArgsIndex[arg.name] = arg
|
|
|
|
})
|
|
|
|
|
|
|
|
const newArgsIndex: Record<string, 1> = {}
|
|
|
|
|
|
|
|
b.arguments.forEach((arg) => {
|
|
|
|
newArgsIndex[arg.name] = 1
|
|
|
|
|
|
|
|
if (!(arg.name in oldArgsIndex)) {
|
|
|
|
argsDiff.added.push(arg)
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const oldArg = oldArgsIndex[arg.name]
|
|
|
|
|
|
|
|
const diff: TlArgumentDiff = {
|
|
|
|
name: arg.name,
|
|
|
|
}
|
|
|
|
|
2023-06-25 03:09:04 +03:00
|
|
|
const argStr = stringifyArgumentType(arg.type, arg.typeModifiers)
|
2023-09-24 01:32:22 +03:00
|
|
|
const oldArgStr = stringifyArgumentType(oldArg.type, oldArg.typeModifiers)
|
2021-11-23 00:03:59 +03:00
|
|
|
|
2023-06-25 03:09:04 +03:00
|
|
|
if (argStr !== oldArgStr) {
|
|
|
|
diff.type = {
|
|
|
|
old: oldArgStr,
|
|
|
|
new: argStr,
|
2021-11-23 00:03:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arg.comment !== oldArg.comment) {
|
|
|
|
diff.comment = {
|
|
|
|
old: oldArg.comment,
|
|
|
|
new: arg.comment,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-25 03:09:04 +03:00
|
|
|
if (diff.type || diff.comment) {
|
2021-11-23 00:03:59 +03:00
|
|
|
argsDiff.modified.push(diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
a.arguments.forEach((arg) => {
|
|
|
|
if (!(arg.name in newArgsIndex)) {
|
|
|
|
argsDiff.removed.push(arg)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2023-09-24 01:32:22 +03:00
|
|
|
if (argsDiff.added.length || argsDiff.removed.length || argsDiff.modified.length) {
|
2021-11-23 00:03:59 +03:00
|
|
|
diff.arguments = argsDiff
|
|
|
|
}
|
|
|
|
|
|
|
|
return diff
|
|
|
|
}
|
|
|
|
|
2022-08-29 14:33:11 +03:00
|
|
|
/**
|
|
|
|
* Compute difference between two TL schemas.
|
|
|
|
*
|
|
|
|
* @param a Entry A (field `old` in diff)
|
|
|
|
* @param b Entry B (field `new` in diff)
|
|
|
|
*/
|
2023-09-24 01:32:22 +03:00
|
|
|
export function generateTlSchemasDifference(a: TlFullSchema, b: TlFullSchema): TlSchemaDiff {
|
2021-11-23 00:03:59 +03:00
|
|
|
// schemas already contain indexes, so we don't need to make our own
|
|
|
|
|
|
|
|
const diff: TlSchemaDiff = {
|
|
|
|
classes: {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
},
|
|
|
|
unions: {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-09-24 01:32:22 +03:00
|
|
|
const unionDiffIndex: Record<string, TlSchemaDiff['unions']['modified'][number]> = {}
|
2021-11-23 00:03:59 +03:00
|
|
|
const unionDiffIndex2: Record<string, 1> = {}
|
|
|
|
|
|
|
|
a.entries.forEach((entry) => {
|
|
|
|
const kind = entry.kind === 'class' ? 'classes' : 'methods'
|
|
|
|
|
|
|
|
// check union
|
|
|
|
const union = a.unions[entry.type]
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
if (!(entry.type in b.unions) && !(entry.type in unionDiffIndex2)) {
|
|
|
|
// deleted union
|
|
|
|
unionDiffIndex2[entry.type] = 1
|
|
|
|
diff.unions.removed.push(union)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(entry.name in b[kind])) {
|
|
|
|
diff[kind].removed.push(entry)
|
|
|
|
|
|
|
|
// we also need to diff the respective union
|
|
|
|
if (entry.type in b.unions) {
|
|
|
|
if (!(entry.type in unionDiffIndex)) {
|
|
|
|
unionDiffIndex[entry.type] = {
|
|
|
|
name: entry.type,
|
|
|
|
classes: {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
diff.unions.modified.push(unionDiffIndex[entry.type])
|
|
|
|
}
|
|
|
|
const unionDiff = unionDiffIndex[entry.type]
|
|
|
|
unionDiff[kind].removed.push(entry)
|
|
|
|
}
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const other = b[kind][entry.name]
|
|
|
|
|
|
|
|
const entryDiff = generateTlEntriesDifference(entry, other)
|
|
|
|
|
2022-06-30 16:32:56 +03:00
|
|
|
if (entryDiff.id || entryDiff.generics || entryDiff.arguments) {
|
2021-11-23 00:03:59 +03:00
|
|
|
diff[kind].modified.push(entryDiff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
b.entries.forEach((entry) => {
|
|
|
|
const kind = entry.kind === 'class' ? 'classes' : 'methods'
|
|
|
|
|
|
|
|
// check union
|
|
|
|
const union = b.unions[entry.type]
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
if (!(entry.type in a.unions) && !(entry.type in unionDiffIndex2)) {
|
|
|
|
// added union
|
|
|
|
unionDiffIndex2[entry.type] = 1
|
|
|
|
diff.unions.added.push(union)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(entry.name in a[kind])) {
|
|
|
|
diff[kind].added.push(entry)
|
|
|
|
|
|
|
|
// we also need to diff the respective union
|
|
|
|
if (entry.type in a.unions) {
|
|
|
|
if (!(entry.type in unionDiffIndex)) {
|
|
|
|
unionDiffIndex[entry.type] = {
|
|
|
|
name: entry.type,
|
|
|
|
classes: {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
added: [],
|
|
|
|
removed: [],
|
|
|
|
modified: [],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
diff.unions.modified.push(unionDiffIndex[entry.type])
|
|
|
|
}
|
|
|
|
const unionDiff = unionDiffIndex[entry.type]
|
|
|
|
unionDiff[kind].added.push(entry)
|
|
|
|
}
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return diff
|
|
|
|
}
|