mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Swift: add structured C++ generated classes
This adds `cppgen`, creating structured C++ classes mirroring QL classes out of `schema.yml`. An example of generated code at the time of this commit can be found [in this gist][1]. [1]: https://gist.github.com/redsun82/57304ddb487a8aa40eaa0caa695048fa Closes https://github.com/github/codeql-c-team/issues/863
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, ClassVar
|
||||
|
||||
@@ -14,13 +15,35 @@ cpp_keywords = {"alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "
|
||||
"typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while",
|
||||
"xor", "xor_eq"}
|
||||
|
||||
_field_overrides = [
|
||||
(re.compile(r"(start|end)_(line|column)|index|num_.*"), {"type": "unsigned"}),
|
||||
(re.compile(r"(.*)_"), lambda m: {"name": m[1]}),
|
||||
]
|
||||
|
||||
|
||||
def get_field_override(field: str):
|
||||
for r, o in _field_overrides:
|
||||
m = r.fullmatch(field)
|
||||
if m:
|
||||
return o(m) if callable(o) else o
|
||||
return {}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Field:
|
||||
name: str
|
||||
type: str
|
||||
is_optional: bool = False
|
||||
is_repeated: bool = False
|
||||
trap_name: str = None
|
||||
first: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
if self.is_optional:
|
||||
self.type = f"std::optional<{self.type}>"
|
||||
elif self.is_repeated:
|
||||
self.type = f"std::vector<{self.type}>"
|
||||
|
||||
@property
|
||||
def cpp_name(self):
|
||||
if self.name in cpp_keywords:
|
||||
@@ -36,6 +59,12 @@ class Field:
|
||||
else:
|
||||
return lambda x: x
|
||||
|
||||
@property
|
||||
def is_single(self):
|
||||
return not (self.is_optional or self.is_repeated)
|
||||
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class Trap:
|
||||
@@ -74,13 +103,48 @@ class Tag:
|
||||
|
||||
@dataclass
|
||||
class TrapList:
|
||||
template: ClassVar = 'cpp_traps'
|
||||
template: ClassVar = 'trap_traps'
|
||||
|
||||
traps: List[Trap] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TagList:
|
||||
template: ClassVar = 'cpp_tags'
|
||||
template: ClassVar = 'trap_tags'
|
||||
|
||||
tags: List[Tag] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ClassBase:
|
||||
ref: 'Class'
|
||||
first: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
class Class:
|
||||
name: str
|
||||
bases: List[ClassBase] = field(default_factory=list)
|
||||
final: bool = False
|
||||
fields: List[Field] = field(default_factory=list)
|
||||
trap_name: str = None
|
||||
|
||||
def __post_init__(self):
|
||||
self.bases = [ClassBase(c) for c in sorted(self.bases, key=lambda cls: cls.name)]
|
||||
if self.bases:
|
||||
self.bases[0].first = True
|
||||
|
||||
@property
|
||||
def has_bases(self):
|
||||
return bool(self.bases)
|
||||
|
||||
@property
|
||||
def single_fields(self):
|
||||
return [f for f in self.fields if f.is_single]
|
||||
|
||||
|
||||
@dataclass
|
||||
class ClassList:
|
||||
template: ClassVar = "cpp_classes"
|
||||
|
||||
classes: List[Class]
|
||||
|
||||
Reference in New Issue
Block a user