Files
codeql/swift/codegen/lib/ql.py
Paolo Tranquilli 946e1f498a Swift: generate getParent implementation
By explicitly marking children in the `schema.yml` file, an internal
`getAChild` predicate is implemented, that is in turn used in `AstNode`
to implement `getParent`.

This is yet to be used in the control flow library to replace the
hand-rolled implementation.

A further, more complex step is to use the same information to fully
generate the core implementation of `PrintAst` (including the
accessor string). This will be done later.

The `parent` tests use the same swift code as the extractor tests, and
this is currently enforced by `sync-files.py`. Notice that `qltest.sh`
had to be modified to deal with multiple files, which was not working
yet.
2022-06-01 14:32:58 +02:00

95 lines
2.1 KiB
Python

import pathlib
from dataclasses import dataclass, field
from typing import List, ClassVar
import inflection
@dataclass
class Param:
param: str
first: bool = False
@dataclass
class Property:
singular: str
type: str = None
tablename: str = None
tableparams: List[Param] = field(default_factory=list)
plural: str = None
first: bool = False
local_var: str = "x"
is_optional: bool = False
is_predicate: bool = False
is_child: bool = False
def __post_init__(self):
if self.tableparams:
if self.type_is_class:
self.tableparams = [x if x != "result" else self.local_var for x in self.tableparams]
self.tableparams = [Param(x) for x in self.tableparams]
self.tableparams[0].first = True
@property
def getter(self):
return f"get{self.singular}" if not self.is_predicate else self.singular
@property
def indefinite_getter(self):
if self.plural:
article = "An" if self.singular[0] in "AEIO" else "A"
return f"get{article}{self.singular}"
@property
def type_is_class(self):
return bool(self.type) and self.type[0].isupper()
@property
def is_repeated(self):
return bool(self.plural)
@dataclass
class Class:
template: ClassVar = 'ql_class'
name: str
bases: List[str] = field(default_factory=list)
final: bool = False
properties: List[Property] = field(default_factory=list)
dir: pathlib.Path = pathlib.Path()
imports: List[str] = field(default_factory=list)
def __post_init__(self):
self.bases = sorted(self.bases)
if self.properties:
self.properties[0].first = True
@property
def db_id(self):
return "@" + inflection.underscore(self.name)
@property
def root(self):
return not self.bases
@property
def path(self):
return self.dir / self.name
@dataclass
class Stub:
template: ClassVar = 'ql_stub'
name: str
base_import: str
@dataclass
class ImportList:
template: ClassVar = 'ql_imports'
imports: List[str] = field(default_factory=list)