mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
129 lines
4.5 KiB
Python
Executable File
129 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import re
|
|
import sys
|
|
|
|
def upperFirst(string):
|
|
return string[0].upper() + string[1:]
|
|
|
|
with open('../ql/src/config/semmlecode.dbscheme', 'r') as f:
|
|
dbscheme = f.read()
|
|
|
|
# Remove comments
|
|
dbscheme = re.sub(r'/\*.*?\*/', '', dbscheme, flags=re.DOTALL)
|
|
dbscheme = re.sub(r'//[^\r\n]*/', '', dbscheme)
|
|
|
|
enums = {}
|
|
type_aliases = {}
|
|
type_hierarchy = {}
|
|
|
|
def unalias(t):
|
|
while t in type_aliases:
|
|
t = type_aliases[t]
|
|
return t
|
|
|
|
def genTable(kt, relname, body, enum = None, kind = None, num = None, typ = None):
|
|
kt.write('fun TrapWriter.write' + upperFirst(relname))
|
|
if kind is not None:
|
|
kt.write('_' + typ)
|
|
kt.write('(')
|
|
for colname, db_type in re.findall('(\S+)\s*:\s*([^\s,]+)', body):
|
|
if colname != kind:
|
|
kt.write(colname + ': ')
|
|
if db_type == 'int':
|
|
# TODO: Do something better if the column is a 'case'
|
|
kt.write('Int')
|
|
elif db_type == 'float':
|
|
kt.write('Double')
|
|
elif db_type == 'string':
|
|
kt.write('String')
|
|
elif db_type == 'date':
|
|
kt.write('String')
|
|
elif db_type == 'boolean':
|
|
kt.write('Boolean')
|
|
elif db_type[0] == '@':
|
|
label = db_type[1:]
|
|
if label == enum:
|
|
label = typ
|
|
kt.write('Label<out Db' + upperFirst(label) + '>')
|
|
else:
|
|
raise Exception('Bad db_type: ' + db_type)
|
|
kt.write(', ')
|
|
kt.write(') {\n')
|
|
kt.write(' this.writeTrap("' + relname + '(')
|
|
comma = ''
|
|
for colname, db_type in re.findall('(\S+)\s*:\s*([^\s,]+)', body):
|
|
kt.write(comma)
|
|
if colname == kind:
|
|
kt.write(str(num))
|
|
elif db_type == 'string' or db_type == 'date':
|
|
kt.write('\\"${escapeTrapString(' + colname + ')}\\"')
|
|
else:
|
|
# TODO: Any reformatting or escaping necessary?
|
|
# e.g. float formats?
|
|
kt.write('$' + colname)
|
|
comma = ', '
|
|
kt.write(')\\n")\n')
|
|
kt.write('}\n')
|
|
|
|
with open('src/main/kotlin/KotlinExtractorDbScheme.kt', 'w') as kt:
|
|
kt.write('/* Generated by ' + sys.argv[0] + ': Do not edit manually. */\n')
|
|
kt.write('package com.github.codeql\n')
|
|
|
|
# kind enums
|
|
for name, kind, body in re.findall(r'case\s+@([^.\s]*)\.([^.\s]*)\s+of\b(.*?);',
|
|
dbscheme,
|
|
flags=re.DOTALL):
|
|
mapping = []
|
|
for num, typ in re.findall(r'(\d+)\s*=\s*@(\S+)', body):
|
|
s = type_hierarchy.get(typ, set())
|
|
s.add(name)
|
|
type_hierarchy[typ] = s
|
|
mapping.append((int(num), typ))
|
|
enums[name] = (kind, mapping)
|
|
|
|
# unions
|
|
for name, unions in re.findall(r'@(\w+)\s*=\s*(@\w+(?:\s*\|\s*@\w+)*)',
|
|
dbscheme,
|
|
flags=re.DOTALL):
|
|
type_hierarchy[name] = type_hierarchy.get(name, set())
|
|
typs = re.findall(r'@(\w+)', unions)
|
|
if len(typs) == 1:
|
|
type_aliases[name] = typs[0]
|
|
else:
|
|
for typ in typs:
|
|
s = type_hierarchy.get(typ, set())
|
|
s.add(name)
|
|
type_hierarchy[typ] = s
|
|
|
|
# tables
|
|
for relname, body in re.findall('\n([\w_]+)(\([^)]*\))',
|
|
dbscheme,
|
|
flags=re.DOTALL):
|
|
enum = None
|
|
for db_type in re.findall(':\s*@([^\s,]+)\s*(?:,|$)', body):
|
|
type_hierarchy[db_type] = type_hierarchy.get(db_type, set())
|
|
if db_type in enums:
|
|
enum = db_type
|
|
if enum is None:
|
|
genTable(kt, relname, body)
|
|
else:
|
|
(kind, mapping) = enums[enum]
|
|
for num, typ in mapping:
|
|
genTable(kt, relname, body, enum, kind, num, typ)
|
|
|
|
for typ in sorted(type_hierarchy):
|
|
if typ in type_aliases:
|
|
kt.write('typealias Db' + upperFirst(typ) + ' = Db' + upperFirst(type_aliases[typ]) + '\n')
|
|
else:
|
|
kt.write('sealed interface Db' + upperFirst(typ))
|
|
# This map of unalias avoids duplicates when both T and an
|
|
# alias of T appear in the set. Sorting makes the output
|
|
# deterministic.
|
|
names = sorted(set(map(unalias, type_hierarchy[typ])))
|
|
if names:
|
|
kt.write(': ')
|
|
kt.write(', '.join(map(lambda name: 'Db' + upperFirst(name), names)))
|
|
kt.write('\n')
|
|
|