mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Merge pull request #9891 from github/redsun82/swift-first-prototype-of-generated-ipa-layer
Swift: first prototype of a generated IPA layer
This commit is contained in:
@@ -83,7 +83,7 @@ class Processor:
|
||||
|
||||
def generate(opts, renderer):
|
||||
assert opts.cpp_output
|
||||
processor = Processor({cls.name: cls for cls in schema.load(opts.schema).classes})
|
||||
processor = Processor(schema.load(opts.schema).classes)
|
||||
out = opts.cpp_output
|
||||
for dir, classes in processor.get_classes().items():
|
||||
include_parent = (dir != pathlib.Path())
|
||||
|
||||
@@ -88,7 +88,7 @@ def cls_to_dbscheme(cls: schema.Class):
|
||||
|
||||
|
||||
def get_declarations(data: schema.Schema):
|
||||
return [d for cls in data.classes for d in cls_to_dbscheme(cls)]
|
||||
return [d for cls in data.classes.values() for d in cls_to_dbscheme(cls)]
|
||||
|
||||
|
||||
def get_includes(data: schema.Schema, include_dir: pathlib.Path, swift_dir: pathlib.Path):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# TODO this should probably be split in different generators now: ql, qltest, maybe qlipa
|
||||
|
||||
import logging
|
||||
import pathlib
|
||||
@@ -8,6 +9,7 @@ import typing
|
||||
import itertools
|
||||
|
||||
import inflection
|
||||
from toposort import toposort_flatten
|
||||
|
||||
from swift.codegen.lib import schema, ql
|
||||
|
||||
@@ -27,8 +29,8 @@ class ModifiedStubMarkedAsGeneratedError(Error):
|
||||
pass
|
||||
|
||||
|
||||
def get_ql_property(cls: schema.Class, prop: schema.Property):
|
||||
common_args = dict(
|
||||
def get_ql_property(cls: schema.Class, prop: schema.Property) -> ql.Property:
|
||||
args = dict(
|
||||
type=prop.type if not prop.is_predicate else "predicate",
|
||||
qltest_skip="qltest_skip" in prop.pragmas,
|
||||
is_child=prop.is_child,
|
||||
@@ -36,39 +38,36 @@ def get_ql_property(cls: schema.Class, prop: schema.Property):
|
||||
is_predicate=prop.is_predicate,
|
||||
)
|
||||
if prop.is_single:
|
||||
return ql.Property(
|
||||
**common_args,
|
||||
args.update(
|
||||
singular=inflection.camelize(prop.name),
|
||||
tablename=inflection.tableize(cls.name),
|
||||
tableparams=[
|
||||
"this"] + ["result" if p is prop else "_" for p in cls.properties if p.is_single],
|
||||
tableparams=["this"] + ["result" if p is prop else "_" for p in cls.properties if p.is_single],
|
||||
)
|
||||
elif prop.is_repeated:
|
||||
return ql.Property(
|
||||
**common_args,
|
||||
args.update(
|
||||
singular=inflection.singularize(inflection.camelize(prop.name)),
|
||||
plural=inflection.pluralize(inflection.camelize(prop.name)),
|
||||
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
|
||||
tableparams=["this", "index", "result"],
|
||||
)
|
||||
elif prop.is_optional:
|
||||
return ql.Property(
|
||||
**common_args,
|
||||
args.update(
|
||||
singular=inflection.camelize(prop.name),
|
||||
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
|
||||
tableparams=["this", "result"],
|
||||
)
|
||||
elif prop.is_predicate:
|
||||
return ql.Property(
|
||||
**common_args,
|
||||
singular=inflection.camelize(
|
||||
prop.name, uppercase_first_letter=False),
|
||||
args.update(
|
||||
singular=inflection.camelize(prop.name, uppercase_first_letter=False),
|
||||
tablename=inflection.underscore(f"{cls.name}_{prop.name}"),
|
||||
tableparams=["this"],
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"unknown property kind for {prop.name} from {cls.name}")
|
||||
return ql.Property(**args)
|
||||
|
||||
|
||||
def get_ql_class(cls: schema.Class):
|
||||
def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
pragmas = {k: True for k in cls.pragmas if k.startswith("ql")}
|
||||
return ql.Class(
|
||||
name=cls.name,
|
||||
@@ -76,10 +75,42 @@ def get_ql_class(cls: schema.Class):
|
||||
final=not cls.derived,
|
||||
properties=[get_ql_property(cls, p) for p in cls.properties],
|
||||
dir=cls.dir,
|
||||
ipa=bool(cls.ipa),
|
||||
**pragmas,
|
||||
)
|
||||
|
||||
|
||||
def _to_db_type(x: str) -> str:
|
||||
if x[0].isupper():
|
||||
return "Raw::" + x
|
||||
return x
|
||||
|
||||
|
||||
_final_db_class_lookup = {}
|
||||
|
||||
|
||||
def get_ql_ipa_class_db(name: str) -> ql.Synth.FinalClassDb:
|
||||
return _final_db_class_lookup.setdefault(name, ql.Synth.FinalClassDb(name=name,
|
||||
params=[
|
||||
ql.Synth.Param("id", _to_db_type(name))]))
|
||||
|
||||
|
||||
def get_ql_ipa_class(cls: schema.Class):
|
||||
if cls.derived:
|
||||
return ql.Synth.NonFinalClass(name=cls.name, derived=sorted(cls.derived),
|
||||
root=(cls.name == schema.root_class_name))
|
||||
if cls.ipa and cls.ipa.from_class is not None:
|
||||
source = cls.ipa.from_class
|
||||
get_ql_ipa_class_db(source).subtract_type(cls.name)
|
||||
return ql.Synth.FinalClassDerivedIpa(name=cls.name,
|
||||
params=[ql.Synth.Param("id", _to_db_type(source))])
|
||||
if cls.ipa and cls.ipa.on_arguments is not None:
|
||||
return ql.Synth.FinalClassFreshIpa(name=cls.name,
|
||||
params=[ql.Synth.Param(k, _to_db_type(v))
|
||||
for k, v in cls.ipa.on_arguments.items()])
|
||||
return get_ql_ipa_class_db(cls.name)
|
||||
|
||||
|
||||
def get_import(file: pathlib.Path, swift_dir: pathlib.Path):
|
||||
stem = file.relative_to(swift_dir / "ql/lib").with_suffix("")
|
||||
return str(stem).replace("/", ".")
|
||||
@@ -96,10 +127,10 @@ def get_classes_used_by(cls: ql.Class):
|
||||
return sorted(set(t for t in get_types_used_by(cls) if t[0].isupper()))
|
||||
|
||||
|
||||
_generated_stub_re = re.compile(r"private import .*\n\nclass \w+ extends \w+ \{[ \n]\}", re.MULTILINE)
|
||||
_generated_stub_re = re.compile(r"\n*private import .*\n+class \w+ extends \w+ \{[ \n]?\}", re.MULTILINE)
|
||||
|
||||
|
||||
def _is_generated_stub(file):
|
||||
def _is_generated_stub(file: pathlib.Path) -> bool:
|
||||
with open(file) as contents:
|
||||
for line in contents:
|
||||
if not line.startswith("// generated"):
|
||||
@@ -108,12 +139,14 @@ def _is_generated_stub(file):
|
||||
else:
|
||||
# no lines
|
||||
return False
|
||||
# one line already read, if we can read 5 other we are past the normal stub generation
|
||||
line_threshold = 5
|
||||
first_lines = list(itertools.islice(contents, line_threshold))
|
||||
if len(first_lines) == line_threshold or not _generated_stub_re.match("".join(first_lines)):
|
||||
raise ModifiedStubMarkedAsGeneratedError(
|
||||
f"{file.name} stub was modified but is still marked as generated")
|
||||
# we still do not detect modified synth constructors
|
||||
if not file.name.endswith("Constructor.qll"):
|
||||
# one line already read, if we can read 5 other we are past the normal stub generation
|
||||
line_threshold = 5
|
||||
first_lines = list(itertools.islice(contents, line_threshold))
|
||||
if len(first_lines) == line_threshold or not _generated_stub_re.match("".join(first_lines)):
|
||||
raise ModifiedStubMarkedAsGeneratedError(
|
||||
f"{file.name} stub was modified but is still marked as generated")
|
||||
return True
|
||||
|
||||
|
||||
@@ -129,45 +162,53 @@ def format(codeql, files):
|
||||
log.debug(line.strip())
|
||||
|
||||
|
||||
def _get_all_properties(cls: ql.Class, lookup: typing.Dict[str, ql.Class]) -> typing.Iterable[
|
||||
typing.Tuple[ql.Class, ql.Property]]:
|
||||
for b in cls.bases:
|
||||
def _get_all_properties(cls: schema.Class, lookup: typing.Dict[str, schema.Class],
|
||||
already_seen: typing.Optional[typing.Set[int]] = None) -> \
|
||||
typing.Iterable[typing.Tuple[schema.Class, schema.Property]]:
|
||||
# deduplicate using ids
|
||||
if already_seen is None:
|
||||
already_seen = set()
|
||||
for b in sorted(cls.bases):
|
||||
base = lookup[b]
|
||||
for item in _get_all_properties(base, lookup):
|
||||
for item in _get_all_properties(base, lookup, already_seen):
|
||||
yield item
|
||||
for p in cls.properties:
|
||||
yield cls, p
|
||||
|
||||
|
||||
def _get_all_properties_to_be_tested(cls: ql.Class, lookup: typing.Dict[str, ql.Class]) -> typing.Iterable[
|
||||
ql.PropertyForTest]:
|
||||
# deduplicate using id
|
||||
already_seen = set()
|
||||
for c, p in _get_all_properties(cls, lookup):
|
||||
if not (c.qltest_skip or p.qltest_skip or id(p) in already_seen):
|
||||
if id(p) not in already_seen:
|
||||
already_seen.add(id(p))
|
||||
yield cls, p
|
||||
|
||||
|
||||
def _get_all_properties_to_be_tested(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> \
|
||||
typing.Iterable[ql.PropertyForTest]:
|
||||
for c, p in _get_all_properties(cls, lookup):
|
||||
if not ("qltest_skip" in c.pragmas or "qltest_skip" in p.pragmas):
|
||||
# TODO here operations are duplicated, but should be better if we split ql and qltest generation
|
||||
p = get_ql_property(c, p)
|
||||
yield ql.PropertyForTest(p.getter, p.type, p.is_single, p.is_predicate, p.is_repeated)
|
||||
|
||||
|
||||
def _partition_iter(x, pred):
|
||||
x1, x2 = itertools.tee(x)
|
||||
return filter(pred, x1), itertools.filterfalse(pred, x2)
|
||||
|
||||
|
||||
def _partition(l, pred):
|
||||
""" partitions a list according to boolean predicate """
|
||||
res = ([], [])
|
||||
for x in l:
|
||||
res[not pred(x)].append(x)
|
||||
return res
|
||||
return map(list, _partition_iter(l, pred))
|
||||
|
||||
|
||||
def _is_in_qltest_collapsed_hierachy(cls: ql.Class, lookup: typing.Dict[str, ql.Class]):
|
||||
return cls.qltest_collapse_hierarchy or _is_under_qltest_collapsed_hierachy(cls, lookup)
|
||||
def _is_in_qltest_collapsed_hierachy(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_collapse_hierarchy" in cls.pragmas or _is_under_qltest_collapsed_hierachy(cls, lookup)
|
||||
|
||||
|
||||
def _is_under_qltest_collapsed_hierachy(cls: ql.Class, lookup: typing.Dict[str, ql.Class]):
|
||||
return not cls.qltest_uncollapse_hierarchy and any(
|
||||
def _is_under_qltest_collapsed_hierachy(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_uncollapse_hierarchy" not in cls.pragmas and any(
|
||||
_is_in_qltest_collapsed_hierachy(lookup[b], lookup) for b in cls.bases)
|
||||
|
||||
|
||||
def _should_skip_qltest(cls: ql.Class, lookup: typing.Dict[str, ql.Class]):
|
||||
return cls.qltest_skip or not (cls.final or cls.qltest_collapse_hierarchy) or _is_under_qltest_collapsed_hierachy(
|
||||
def _should_skip_qltest(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_skip" in cls.pragmas or not (
|
||||
cls.final or "qltest_collapse_hierarchy" in cls.pragmas) or _is_under_qltest_collapsed_hierachy(
|
||||
cls, lookup)
|
||||
|
||||
|
||||
@@ -185,15 +226,18 @@ def generate(opts, renderer):
|
||||
|
||||
data = schema.load(input)
|
||||
|
||||
classes = [get_ql_class(cls) for cls in data.classes]
|
||||
lookup = {cls.name: cls for cls in classes}
|
||||
classes.sort(key=lambda cls: (cls.dir, cls.name))
|
||||
classes = {name: get_ql_class(cls, data.classes) for name, cls in data.classes.items()}
|
||||
imports = {}
|
||||
|
||||
for c in classes:
|
||||
inheritance_graph = {name: cls.bases for name, cls in data.classes.items()}
|
||||
db_classes = [classes[name] for name in toposort_flatten(inheritance_graph) if not classes[name].ipa]
|
||||
renderer.render(ql.DbClasses(db_classes), out / "Raw.qll")
|
||||
|
||||
classes_by_dir_and_name = sorted(classes.values(), key=lambda cls: (cls.dir, cls.name))
|
||||
for c in classes_by_dir_and_name:
|
||||
imports[c.name] = get_import(stub_out / c.path, opts.swift_dir)
|
||||
|
||||
for c in classes:
|
||||
for c in classes.values():
|
||||
qll = out / c.path.with_suffix(".qll")
|
||||
c.imports = [imports[t] for t in get_classes_used_by(c)]
|
||||
renderer.render(c, qll)
|
||||
@@ -207,20 +251,19 @@ def generate(opts, renderer):
|
||||
include_file = stub_out.with_suffix(".qll")
|
||||
renderer.render(ql.ImportList(list(imports.values())), include_file)
|
||||
|
||||
renderer.render(ql.GetParentImplementation(
|
||||
classes), out / 'GetImmediateParent.qll')
|
||||
renderer.render(ql.GetParentImplementation(classes_by_dir_and_name), out / 'GetImmediateParent.qll')
|
||||
|
||||
for c in classes:
|
||||
if _should_skip_qltest(c, lookup):
|
||||
for c in data.classes.values():
|
||||
if _should_skip_qltest(c, data.classes):
|
||||
continue
|
||||
test_dir = test_out / c.path
|
||||
test_dir = test_out / c.dir / c.name
|
||||
test_dir.mkdir(parents=True, exist_ok=True)
|
||||
if not any(test_dir.glob("*.swift")):
|
||||
log.warning(f"no test source in {c.path}")
|
||||
log.warning(f"no test source in {c.dir / c.name}")
|
||||
renderer.render(ql.MissingTestInstructions(),
|
||||
test_dir / missing_test_source_filename)
|
||||
continue
|
||||
total_props, partial_props = _partition(_get_all_properties_to_be_tested(c, lookup),
|
||||
total_props, partial_props = _partition(_get_all_properties_to_be_tested(c, data.classes),
|
||||
lambda p: p.is_single or p.is_predicate)
|
||||
renderer.render(ql.ClassTester(class_name=c.name,
|
||||
properties=total_props), test_dir / f"{c.name}.ql")
|
||||
@@ -228,6 +271,29 @@ def generate(opts, renderer):
|
||||
renderer.render(ql.PropertyTester(class_name=c.name,
|
||||
property=p), test_dir / f"{c.name}_{p.getter}.ql")
|
||||
|
||||
final_ipa_types = []
|
||||
non_final_ipa_types = []
|
||||
constructor_imports = []
|
||||
ipa_constructor_imports = []
|
||||
for cls in sorted(data.classes.values(), key=lambda cls: (cls.dir, cls.name)):
|
||||
ipa_type = get_ql_ipa_class(cls)
|
||||
if ipa_type.is_final:
|
||||
final_ipa_types.append(ipa_type)
|
||||
if ipa_type.has_params:
|
||||
stub_file = stub_out / cls.dir / f"{cls.name}Constructor.qll"
|
||||
if not stub_file.is_file() or _is_generated_stub(stub_file):
|
||||
renderer.render(ql.Synth.ConstructorStub(ipa_type), stub_file)
|
||||
constructor_import = get_import(stub_file, opts.swift_dir)
|
||||
constructor_imports.append(constructor_import)
|
||||
if ipa_type.is_ipa:
|
||||
ipa_constructor_imports.append(constructor_import)
|
||||
else:
|
||||
non_final_ipa_types.append(ipa_type)
|
||||
|
||||
renderer.render(ql.Synth.Types(schema.root_class_name, final_ipa_types, non_final_ipa_types), out / "Synth.qll")
|
||||
renderer.render(ql.ImportList(constructor_imports), out / "SynthConstructors.qll")
|
||||
renderer.render(ql.ImportList(ipa_constructor_imports), out / "PureSynthConstructors.qll")
|
||||
|
||||
renderer.cleanup(existing)
|
||||
if opts.ql_format:
|
||||
format(opts.codeql_binary, renderer.written)
|
||||
|
||||
@@ -14,7 +14,7 @@ left behind and must be dealt with by hand.
|
||||
|
||||
import pathlib
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, ClassVar
|
||||
from typing import List, ClassVar, Union, Optional
|
||||
|
||||
import inflection
|
||||
|
||||
@@ -28,12 +28,11 @@ class Param:
|
||||
@dataclass
|
||||
class Property:
|
||||
singular: str
|
||||
type: str = None
|
||||
tablename: str = None
|
||||
type: Optional[str] = None
|
||||
tablename: Optional[str] = None
|
||||
tableparams: List[Param] = field(default_factory=list)
|
||||
plural: str = None
|
||||
plural: Optional[str] = None
|
||||
first: bool = False
|
||||
local_var: str = "x"
|
||||
is_optional: bool = False
|
||||
is_predicate: bool = False
|
||||
is_child: bool = False
|
||||
@@ -41,8 +40,6 @@ class Property:
|
||||
|
||||
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
|
||||
|
||||
@@ -82,6 +79,7 @@ class Class:
|
||||
qltest_skip: bool = False
|
||||
qltest_collapse_hierarchy: bool = False
|
||||
qltest_uncollapse_hierarchy: bool = False
|
||||
ipa: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
self.bases = sorted(self.bases)
|
||||
@@ -89,17 +87,17 @@ class Class:
|
||||
self.properties[0].first = True
|
||||
|
||||
@property
|
||||
def db_id(self):
|
||||
return "@" + inflection.underscore(self.name)
|
||||
|
||||
@property
|
||||
def root(self):
|
||||
def root(self) -> bool:
|
||||
return not self.bases
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
def path(self) -> pathlib.Path:
|
||||
return self.dir / self.name
|
||||
|
||||
@property
|
||||
def db_id(self):
|
||||
return "@" + inflection.underscore(self.name)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Stub:
|
||||
@@ -109,6 +107,13 @@ class Stub:
|
||||
base_import: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class DbClasses:
|
||||
template: ClassVar = 'ql_db'
|
||||
|
||||
classes: List[Class] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ImportList:
|
||||
template: ClassVar = 'ql_imports'
|
||||
@@ -126,7 +131,7 @@ class GetParentImplementation:
|
||||
@dataclass
|
||||
class PropertyForTest:
|
||||
getter: str
|
||||
type: str = None
|
||||
type: Optional[str] = None
|
||||
is_single: bool = False
|
||||
is_predicate: bool = False
|
||||
is_repeated: bool = False
|
||||
@@ -151,3 +156,96 @@ class PropertyTester:
|
||||
@dataclass
|
||||
class MissingTestInstructions:
|
||||
template: ClassVar = 'ql_test_missing'
|
||||
|
||||
|
||||
class Synth:
|
||||
@dataclass
|
||||
class Class:
|
||||
is_final: ClassVar = False
|
||||
|
||||
name: str
|
||||
first: bool = False
|
||||
|
||||
@dataclass
|
||||
class Param:
|
||||
param: str
|
||||
type: str
|
||||
first: bool = False
|
||||
|
||||
@dataclass
|
||||
class FinalClass(Class):
|
||||
is_final: ClassVar = True
|
||||
is_derived_ipa: ClassVar = False
|
||||
is_fresh_ipa: ClassVar = False
|
||||
is_db: ClassVar = False
|
||||
|
||||
params: List["Synth.Param"] = field(default_factory=list)
|
||||
|
||||
def __post_init__(self):
|
||||
if self.params:
|
||||
self.params[0].first = True
|
||||
|
||||
@property
|
||||
def is_ipa(self):
|
||||
return self.is_fresh_ipa or self.is_derived_ipa
|
||||
|
||||
@property
|
||||
def has_params(self) -> bool:
|
||||
return bool(self.params)
|
||||
|
||||
@dataclass
|
||||
class FinalClassIpa(FinalClass):
|
||||
pass
|
||||
|
||||
@dataclass
|
||||
class FinalClassDerivedIpa(FinalClassIpa):
|
||||
is_derived_ipa: ClassVar = True
|
||||
|
||||
@dataclass
|
||||
class FinalClassFreshIpa(FinalClassIpa):
|
||||
is_fresh_ipa: ClassVar = True
|
||||
|
||||
@dataclass
|
||||
class FinalClassDb(FinalClass):
|
||||
is_db: ClassVar = True
|
||||
|
||||
subtracted_ipa_types: List["Synth.Class"] = field(default_factory=list)
|
||||
|
||||
def subtract_type(self, type: str):
|
||||
self.subtracted_ipa_types.append(Synth.Class(type, first=not self.subtracted_ipa_types))
|
||||
|
||||
@property
|
||||
def has_subtracted_ipa_types(self) -> bool:
|
||||
return bool(self.subtracted_ipa_types)
|
||||
|
||||
@property
|
||||
def db_id(self) -> str:
|
||||
return "@" + inflection.underscore(self.name)
|
||||
|
||||
@dataclass
|
||||
class NonFinalClass(Class):
|
||||
derived: List["Synth.Class"] = field(default_factory=list)
|
||||
root: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
self.derived = [Synth.Class(c) for c in self.derived]
|
||||
if self.derived:
|
||||
self.derived[0].first = True
|
||||
|
||||
@dataclass
|
||||
class Types:
|
||||
template: ClassVar = "ql_ipa_types"
|
||||
|
||||
root: str
|
||||
final_classes: List["Synth.FinalClass"] = field(default_factory=list)
|
||||
non_final_classes: List["Synth.NonFinalClass"] = field(default_factory=list)
|
||||
|
||||
def __post_init__(self):
|
||||
if self.final_classes:
|
||||
self.final_classes[0].first = True
|
||||
|
||||
@dataclass
|
||||
class ConstructorStub:
|
||||
template: ClassVar = "ql_ipa_constructor_stub"
|
||||
|
||||
cls: "Synth.FinalClass"
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
import pathlib
|
||||
import re
|
||||
import typing
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Set, Union, Dict, ClassVar
|
||||
from typing import List, Set, Union, Dict, ClassVar, Optional
|
||||
|
||||
import yaml
|
||||
|
||||
@@ -57,6 +56,12 @@ class PredicateProperty(Property):
|
||||
is_predicate: ClassVar = True
|
||||
|
||||
|
||||
@dataclass
|
||||
class IpaInfo:
|
||||
from_class: Optional[str] = None
|
||||
on_arguments: Optional[Dict[str, str]] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Class:
|
||||
name: str
|
||||
@@ -65,11 +70,16 @@ class Class:
|
||||
properties: List[Property] = field(default_factory=list)
|
||||
dir: pathlib.Path = pathlib.Path()
|
||||
pragmas: List[str] = field(default_factory=list)
|
||||
ipa: Optional[IpaInfo] = None
|
||||
|
||||
@property
|
||||
def final(self):
|
||||
return not self.derived
|
||||
|
||||
|
||||
@dataclass
|
||||
class Schema:
|
||||
classes: List[Class]
|
||||
classes: Dict[str, Class]
|
||||
includes: Set[str] = field(default_factory=set)
|
||||
|
||||
|
||||
@@ -107,6 +117,11 @@ def _parse_property(name: str, data: Union[str, Dict[str, _StrOrList]], is_child
|
||||
return SingleProperty(name, type, is_child=is_child, pragmas=pragmas)
|
||||
|
||||
|
||||
def _parse_ipa(data: Dict[str, Union[str, Dict[str, str]]]):
|
||||
return IpaInfo(from_class=data.get("from"),
|
||||
on_arguments=data.get(True)) # 'on' is parsed as boolean True in yaml
|
||||
|
||||
|
||||
class _DirSelector:
|
||||
""" Default output subdirectory selector for generated QL files, based on the `_directories` global field"""
|
||||
|
||||
@@ -145,10 +160,12 @@ def load(path):
|
||||
cls.properties.extend(_parse_property(kk, vv, is_child=True) for kk, vv in v.items())
|
||||
elif k == "_pragma":
|
||||
cls.pragmas = _auto_list(v)
|
||||
elif k == "_synth":
|
||||
cls.ipa = _parse_ipa(v)
|
||||
else:
|
||||
raise Error(f"unknown metadata {k} for class {name}")
|
||||
if not cls.bases and cls.name != root_class_name:
|
||||
cls.bases.add(root_class_name)
|
||||
classes[root_class_name].derived.add(name)
|
||||
|
||||
return Schema(classes=list(classes.values()), includes=set(data.get("_includes", [])))
|
||||
return Schema(classes=classes, includes=set(data.get("_includes", [])))
|
||||
|
||||
@@ -19,6 +19,15 @@ Element:
|
||||
|
||||
File:
|
||||
name: string
|
||||
_pragma: qltest_collapse_hierarchy
|
||||
|
||||
DbFile:
|
||||
_extends: File
|
||||
|
||||
UnknownFile:
|
||||
_extends: File
|
||||
_synth:
|
||||
on: {}
|
||||
|
||||
Locatable:
|
||||
location:
|
||||
@@ -32,7 +41,15 @@ Location:
|
||||
start_column: int
|
||||
end_line: int
|
||||
end_column: int
|
||||
_pragma: qltest_skip
|
||||
_pragma: [qltest_skip, qltest_collapse_hierarchy]
|
||||
|
||||
DbLocation:
|
||||
_extends: Location
|
||||
|
||||
UnknownLocation:
|
||||
_extends: Location
|
||||
_synth:
|
||||
on: {}
|
||||
|
||||
Comment:
|
||||
_extends: Locatable
|
||||
@@ -411,7 +428,7 @@ EnumIsCaseExpr:
|
||||
_extends: Expr
|
||||
_children:
|
||||
sub_expr: Expr
|
||||
element: EnumElementDecl
|
||||
element: EnumElementDecl
|
||||
|
||||
ErrorExpr:
|
||||
_extends: Expr
|
||||
@@ -797,6 +814,12 @@ OptionalTryExpr:
|
||||
TryExpr:
|
||||
_extends: AnyTryExpr
|
||||
|
||||
#MethodCallExpr:
|
||||
# _extends: ApplyExpr
|
||||
# _synth:
|
||||
# from: CallExpr
|
||||
# qualifier: Expr
|
||||
|
||||
BinaryExpr:
|
||||
_extends: ApplyExpr
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// generated by {{generator}}
|
||||
|
||||
private import codeql.swift.generated.Synth
|
||||
private import codeql.swift.generated.Raw
|
||||
{{#imports}}
|
||||
import {{.}}
|
||||
{{/imports}}
|
||||
|
||||
class {{name}}Base extends {{db_id}}{{#bases}}, {{.}}{{/bases}} {
|
||||
class {{name}}Base extends Synth::T{{name}}{{#bases}}, {{.}}{{/bases}} {
|
||||
{{#root}}
|
||||
string toString() { none() } // overridden by subclasses
|
||||
|
||||
@@ -25,31 +26,45 @@ class {{name}}Base extends {{db_id}}{{#bases}}, {{.}}{{/bases}} {
|
||||
{{/final}}
|
||||
{{#properties}}
|
||||
|
||||
{{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
{{#type_is_class}}
|
||||
exists({{type}} {{local_var}} |
|
||||
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
|
||||
and
|
||||
result = {{local_var}}.resolve())
|
||||
{{/type_is_class}}
|
||||
{{^type_is_class}}
|
||||
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
|
||||
{{/type_is_class}}
|
||||
{{#type_is_class}}
|
||||
{{type}} getImmediate{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
{{^ipa}}
|
||||
result = Synth::convert{{type}}FromRaw(Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}}))
|
||||
{{/ipa}}
|
||||
{{#ipa}}
|
||||
none()
|
||||
{{/ipa}}
|
||||
}
|
||||
{{#is_optional}}
|
||||
|
||||
predicate has{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
final {{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
result = getImmediate{{singular}}({{#is_repeated}}index{{/is_repeated}}).resolve()
|
||||
}
|
||||
|
||||
{{/type_is_class}}
|
||||
{{^type_is_class}}
|
||||
{{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
{{^ipa}}
|
||||
{{^is_predicate}}result = {{/is_predicate}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}})
|
||||
{{/ipa}}
|
||||
{{#ipa}}
|
||||
none()
|
||||
{{/ipa}}
|
||||
}
|
||||
|
||||
{{/type_is_class}}
|
||||
{{#is_optional}}
|
||||
final predicate has{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
exists({{getter}}({{#is_repeated}}index{{/is_repeated}}))
|
||||
}
|
||||
{{/is_optional}}
|
||||
{{#is_repeated}}
|
||||
|
||||
{{type}} {{indefinite_getter}}() {
|
||||
final {{type}} {{indefinite_getter}}() {
|
||||
result = {{getter}}(_)
|
||||
}
|
||||
{{^is_optional}}
|
||||
|
||||
int getNumberOf{{plural}}() {
|
||||
final int getNumberOf{{plural}}() {
|
||||
result = count({{indefinite_getter}}())
|
||||
}
|
||||
{{/is_optional}}
|
||||
|
||||
15
swift/codegen/templates/ql_db.mustache
Normal file
15
swift/codegen/templates/ql_db.mustache
Normal file
@@ -0,0 +1,15 @@
|
||||
module Raw {
|
||||
{{#classes}}
|
||||
class {{name}} extends {{db_id}}{{#bases}}, {{.}}{{/bases}} {
|
||||
{{#root}}string toString() { none() }{{/root}}
|
||||
{{#final}}override string toString() { result = "{{name}}" }{{/final}}
|
||||
|
||||
{{#properties}}
|
||||
{{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
|
||||
}
|
||||
{{/properties}}
|
||||
}
|
||||
|
||||
{{/classes}}
|
||||
}
|
||||
19
swift/codegen/templates/ql_ipa_constructor_stub.mustache
Normal file
19
swift/codegen/templates/ql_ipa_constructor_stub.mustache
Normal file
@@ -0,0 +1,19 @@
|
||||
// generated by {{generator}}, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
{{#cls}}
|
||||
{{#is_db}}
|
||||
{{#has_subtracted_ipa_types}}
|
||||
private import codeql.swift.generated.PureSynthConstructors
|
||||
{{/has_subtracted_ipa_types}}
|
||||
{{/is_db}}
|
||||
|
||||
predicate construct{{name}}({{#params}}{{^first}}, {{/first}}{{type}} {{param}}{{/params}}) {
|
||||
{{#is_db}}
|
||||
{{#subtracted_ipa_types}}{{^first}} and {{/first}}not construct{{name}}(id){{/subtracted_ipa_types}}
|
||||
{{^subtracted_ipa_types}}any(){{/subtracted_ipa_types}}
|
||||
{{/is_db}}
|
||||
{{^is_db}}
|
||||
none()
|
||||
{{/is_db}}
|
||||
}
|
||||
{{/cls}}
|
||||
62
swift/codegen/templates/ql_ipa_types.mustache
Normal file
62
swift/codegen/templates/ql_ipa_types.mustache
Normal file
@@ -0,0 +1,62 @@
|
||||
private import codeql.swift.generated.SynthConstructors
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
cached module Synth {
|
||||
cached newtype T{{root}} =
|
||||
{{#final_classes}}
|
||||
{{^first}}
|
||||
or
|
||||
{{/first}}
|
||||
T{{name}}({{#params}}{{^first}}, {{/first}}{{type}} {{param}}{{/params}}){{#has_params}} { construct{{name}}({{#params}}{{^first}}, {{/first}}{{param}}{{/params}}) }{{/has_params}}
|
||||
{{/final_classes}}
|
||||
|
||||
{{#non_final_classes}}
|
||||
{{^root}}
|
||||
class T{{name}} = {{#derived}}{{^first}} or {{/first}}T{{name}}{{/derived}};
|
||||
{{/root}}
|
||||
{{/non_final_classes}}
|
||||
|
||||
{{#final_classes}}
|
||||
cached T{{name}} convert{{name}}FromRaw(Raw::Element e) {
|
||||
{{^is_fresh_ipa}}
|
||||
result = T{{name}}(e)
|
||||
{{/is_fresh_ipa}}
|
||||
{{#is_fresh_ipa}}
|
||||
none()
|
||||
{{/is_fresh_ipa}}
|
||||
}
|
||||
{{/final_classes}}
|
||||
|
||||
{{#non_final_classes}}
|
||||
cached T{{name}} convert{{name}}FromRaw(Raw::Element e) {
|
||||
{{#derived}}
|
||||
{{^first}}
|
||||
or
|
||||
{{/first}}
|
||||
result = convert{{name}}FromRaw(e)
|
||||
{{/derived}}
|
||||
}
|
||||
{{/non_final_classes}}
|
||||
|
||||
{{#final_classes}}
|
||||
cached Raw::Element convert{{name}}ToRaw(T{{name}} e) {
|
||||
{{^is_fresh_ipa}}
|
||||
e = T{{name}}(result)
|
||||
{{/is_fresh_ipa}}
|
||||
{{#is_fresh_ipa}}
|
||||
none()
|
||||
{{/is_fresh_ipa}}
|
||||
}
|
||||
{{/final_classes}}
|
||||
|
||||
{{#non_final_classes}}
|
||||
cached Raw::Element convert{{name}}ToRaw(T{{name}} e) {
|
||||
{{#derived}}
|
||||
{{^first}}
|
||||
or
|
||||
{{/first}}
|
||||
result = convert{{name}}ToRaw(e)
|
||||
{{/derived}}
|
||||
}
|
||||
{{/non_final_classes}}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// generated by {{generator}}
|
||||
|
||||
import codeql.swift.elements.Element
|
||||
import codeql.swift.elements
|
||||
|
||||
/**
|
||||
* Gets any of the "immediate" children of `e`. "Immediate" means not taking into account node resolution: for example
|
||||
@@ -11,25 +11,16 @@ import codeql.swift.elements.Element
|
||||
cached
|
||||
Element getAnImmediateChild(Element e) {
|
||||
// why does this look more complicated than it should?
|
||||
// * `exists` and the `x` variable are there to reuse the same generation done in classes (where `x` is used to hide
|
||||
// nodes via resolution)
|
||||
// * none() simplifies generation, as we can append `or ...` without a special case for the first item
|
||||
exists(Element x | result = x and (
|
||||
none()
|
||||
{{#classes}}
|
||||
{{#properties}}
|
||||
{{#is_child}}
|
||||
or
|
||||
{{#is_repeated}}
|
||||
{{tablename}}(e, _, x)
|
||||
{{/is_repeated}}
|
||||
{{^is_repeated}}
|
||||
{{tablename}}(e{{#tableparams}}{{^first}}, {{param}}{{/first}}{{/tableparams}})
|
||||
{{/is_repeated}}
|
||||
{{/is_child}}
|
||||
{{/properties}}
|
||||
{{/classes}}
|
||||
))
|
||||
none()
|
||||
{{#classes}}
|
||||
{{#properties}}
|
||||
{{#is_child}}
|
||||
or
|
||||
result = e.({{name}}).getImmediate{{singular}}({{#is_repeated}}_{{/is_repeated}})
|
||||
{{/is_child}}
|
||||
{{/properties}}
|
||||
{{/classes}}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// generated by {{generator}}, remove this comment if you wish to edit this file
|
||||
|
||||
private import {{base_import}}
|
||||
|
||||
class {{name}} extends {{name}}Base {}
|
||||
|
||||
@@ -12,7 +12,7 @@ def generate_grouped(opts, renderer, input):
|
||||
opts.cpp_output = output_dir
|
||||
|
||||
def ret(classes):
|
||||
input.classes = classes
|
||||
input.classes = {cls.name: cls for cls in classes}
|
||||
generated = run_generation(cppgen.generate, opts, renderer)
|
||||
for f, g in generated.items():
|
||||
assert isinstance(g, cpp.ClassList), f
|
||||
|
||||
@@ -8,7 +8,6 @@ from swift.codegen.generators import dbschemegen
|
||||
from swift.codegen.lib import dbscheme
|
||||
from swift.codegen.test.utils import *
|
||||
|
||||
|
||||
InputExpectedPair = collections.namedtuple("InputExpectedPair", ("input", "expected"))
|
||||
|
||||
|
||||
@@ -20,27 +19,32 @@ def dir_param(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def generate(opts, renderer):
|
||||
(out, data), = run_generation(dbschemegen.generate, opts, renderer).items()
|
||||
assert out is opts.dbscheme
|
||||
return data
|
||||
@pytest.fixture
|
||||
def generate(opts, input, renderer):
|
||||
def func(classes):
|
||||
input.classes = {cls.name: cls for cls in classes}
|
||||
(out, data), = run_generation(dbschemegen.generate, opts, renderer).items()
|
||||
assert out is opts.dbscheme
|
||||
return data
|
||||
|
||||
return func
|
||||
|
||||
|
||||
def test_empty(opts, input, renderer):
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
def test_empty(generate):
|
||||
assert generate([]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[],
|
||||
)
|
||||
|
||||
|
||||
def test_includes(opts, input, renderer):
|
||||
def test_includes(input, opts, generate):
|
||||
includes = ["foo", "bar"]
|
||||
input.includes = includes
|
||||
for i in includes:
|
||||
write(opts.schema.parent / i, i + " data")
|
||||
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
assert generate([]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[
|
||||
dbscheme.SchemeInclude(
|
||||
@@ -52,11 +56,10 @@ def test_includes(opts, input, renderer):
|
||||
)
|
||||
|
||||
|
||||
def test_empty_final_class(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_empty_final_class(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class("Object", dir=dir_param.input),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -71,14 +74,12 @@ def test_empty_final_class(opts, input, renderer, dir_param):
|
||||
)
|
||||
|
||||
|
||||
def test_final_class_with_single_scalar_field(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
|
||||
def test_final_class_with_single_scalar_field(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class("Object", dir=dir_param.input, properties=[
|
||||
schema.SingleProperty("foo", "bar"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -93,13 +94,12 @@ def test_final_class_with_single_scalar_field(opts, input, renderer, dir_param):
|
||||
)
|
||||
|
||||
|
||||
def test_final_class_with_single_class_field(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_final_class_with_single_class_field(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class("Object", dir=dir_param.input, properties=[
|
||||
schema.SingleProperty("foo", "Bar"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -114,13 +114,12 @@ def test_final_class_with_single_class_field(opts, input, renderer, dir_param):
|
||||
)
|
||||
|
||||
|
||||
def test_final_class_with_optional_field(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_final_class_with_optional_field(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class("Object", dir=dir_param.input, properties=[
|
||||
schema.OptionalProperty("foo", "bar"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -143,13 +142,12 @@ def test_final_class_with_optional_field(opts, input, renderer, dir_param):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("property_cls", [schema.RepeatedProperty, schema.RepeatedOptionalProperty])
|
||||
def test_final_class_with_repeated_field(opts, input, renderer, property_cls, dir_param):
|
||||
input.classes = [
|
||||
def test_final_class_with_repeated_field(generate, property_cls, dir_param):
|
||||
assert generate([
|
||||
schema.Class("Object", dir=dir_param.input, properties=[
|
||||
property_cls("foo", "bar"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -172,13 +170,12 @@ def test_final_class_with_repeated_field(opts, input, renderer, property_cls, di
|
||||
)
|
||||
|
||||
|
||||
def test_final_class_with_predicate_field(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_final_class_with_predicate_field(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class("Object", dir=dir_param.input, properties=[
|
||||
schema.PredicateProperty("foo"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -199,8 +196,8 @@ def test_final_class_with_predicate_field(opts, input, renderer, dir_param):
|
||||
)
|
||||
|
||||
|
||||
def test_final_class_with_more_fields(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_final_class_with_more_fields(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class("Object", dir=dir_param.input, properties=[
|
||||
schema.SingleProperty("one", "x"),
|
||||
schema.SingleProperty("two", "y"),
|
||||
@@ -209,8 +206,7 @@ def test_final_class_with_more_fields(opts, input, renderer, dir_param):
|
||||
schema.RepeatedOptionalProperty("five", "v"),
|
||||
schema.PredicateProperty("six"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -259,12 +255,11 @@ def test_final_class_with_more_fields(opts, input, renderer, dir_param):
|
||||
)
|
||||
|
||||
|
||||
def test_empty_class_with_derived(opts, input, renderer):
|
||||
input.classes = [
|
||||
def test_empty_class_with_derived(generate):
|
||||
assert generate([
|
||||
schema.Class(
|
||||
name="Base", derived={"Left", "Right"}),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -276,8 +271,8 @@ def test_empty_class_with_derived(opts, input, renderer):
|
||||
)
|
||||
|
||||
|
||||
def test_class_with_derived_and_single_property(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_class_with_derived_and_single_property(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class(
|
||||
name="Base",
|
||||
derived={"Left", "Right"},
|
||||
@@ -285,8 +280,7 @@ def test_class_with_derived_and_single_property(opts, input, renderer, dir_param
|
||||
properties=[
|
||||
schema.SingleProperty("single", "Prop"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -307,8 +301,8 @@ def test_class_with_derived_and_single_property(opts, input, renderer, dir_param
|
||||
)
|
||||
|
||||
|
||||
def test_class_with_derived_and_optional_property(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_class_with_derived_and_optional_property(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class(
|
||||
name="Base",
|
||||
derived={"Left", "Right"},
|
||||
@@ -316,8 +310,7 @@ def test_class_with_derived_and_optional_property(opts, input, renderer, dir_par
|
||||
properties=[
|
||||
schema.OptionalProperty("opt", "Prop"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
@@ -338,8 +331,8 @@ def test_class_with_derived_and_optional_property(opts, input, renderer, dir_par
|
||||
)
|
||||
|
||||
|
||||
def test_class_with_derived_and_repeated_property(opts, input, renderer, dir_param):
|
||||
input.classes = [
|
||||
def test_class_with_derived_and_repeated_property(generate, dir_param):
|
||||
assert generate([
|
||||
schema.Class(
|
||||
name="Base",
|
||||
dir=dir_param.input,
|
||||
@@ -347,8 +340,7 @@ def test_class_with_derived_and_repeated_property(opts, input, renderer, dir_par
|
||||
properties=[
|
||||
schema.RepeatedProperty("rep", "Prop"),
|
||||
]),
|
||||
]
|
||||
assert generate(opts, renderer) == dbscheme.Scheme(
|
||||
]) == dbscheme.Scheme(
|
||||
src=schema_file,
|
||||
includes=[],
|
||||
declarations=[
|
||||
|
||||
@@ -21,7 +21,7 @@ def test_property_has_first_table_param_marked():
|
||||
])
|
||||
def test_property_is_a_class(type, expected):
|
||||
tableparams = ["a", "result", "b"]
|
||||
expected_tableparams = ["a", "x" if expected else "result", "b"]
|
||||
expected_tableparams = ["a", "result" if expected else "result", "b"]
|
||||
prop = ql.Property("Prop", type, tableparams=tableparams)
|
||||
assert prop.type_is_class is expected
|
||||
assert [p.param for p in prop.tableparams] == expected_tableparams
|
||||
@@ -46,7 +46,7 @@ def test_property_indefinite_article(name, expected_getter):
|
||||
("X", True),
|
||||
])
|
||||
def test_property_is_repeated(plural, expected):
|
||||
prop = ql.Property("foo", "Foo", "props", ["x"], plural=plural)
|
||||
prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural)
|
||||
assert prop.is_repeated is expected
|
||||
|
||||
|
||||
@@ -58,12 +58,13 @@ def test_property_is_repeated(plural, expected):
|
||||
(False, True, None, False),
|
||||
])
|
||||
def test_property_is_single(is_optional, is_predicate, plural, expected):
|
||||
prop = ql.Property("foo", "Foo", "props", ["x"], plural=plural, is_predicate=is_predicate, is_optional=is_optional)
|
||||
prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural,
|
||||
is_predicate=is_predicate, is_optional=is_optional)
|
||||
assert prop.is_single is expected
|
||||
|
||||
|
||||
def test_property_no_plural_no_indefinite_getter():
|
||||
prop = ql.Property("Prop", "Foo", "props", ["x"])
|
||||
prop = ql.Property("Prop", "Foo", "props", ["result"])
|
||||
assert prop.indefinite_getter is None
|
||||
|
||||
|
||||
@@ -94,11 +95,6 @@ def test_class_has_first_property_marked():
|
||||
assert cls.properties == expected
|
||||
|
||||
|
||||
def test_class_db_id():
|
||||
cls = ql.Class("ThisIsMyClass")
|
||||
assert cls.db_id == "@this_is_my_class"
|
||||
|
||||
|
||||
def test_root_class():
|
||||
cls = ql.Class("Class")
|
||||
assert cls.root
|
||||
|
||||
@@ -52,7 +52,7 @@ def generate(input, qlgen_opts, renderer):
|
||||
renderer.written = []
|
||||
|
||||
def func(classes):
|
||||
input.classes = classes
|
||||
input.classes = {cls.name: cls for cls in classes}
|
||||
return run_generation(qlgen.generate, qlgen_opts, renderer)
|
||||
|
||||
return func
|
||||
@@ -101,7 +101,9 @@ def _filter_generated_classes(ret, output_test_files=False):
|
||||
str(f): ret[ql_test_output_path() / f]
|
||||
for f in test_files
|
||||
}
|
||||
assert stub_files == base_files
|
||||
base_files -= {pathlib.Path(f"{name}.qll") for name in
|
||||
("Raw", "Synth", "SynthConstructors", "PureSynthConstructors")}
|
||||
assert base_files <= stub_files
|
||||
return {
|
||||
str(f): (ret[stub_path() / f], ret[ql_output_path() / f])
|
||||
for f in base_files
|
||||
@@ -128,6 +130,11 @@ def test_empty(generate):
|
||||
assert generate([]) == {
|
||||
import_file(): ql.ImportList(),
|
||||
children_file(): ql.GetParentImplementation(),
|
||||
ql_output_path() / "Synth.qll": ql.Synth.Types(schema.root_class_name),
|
||||
ql_output_path() / "SynthConstructors.qll": ql.ImportList(),
|
||||
ql_output_path() / "PureSynthConstructors.qll": ql.ImportList(),
|
||||
ql_output_path() / "Raw.qll": ql.DbClasses(),
|
||||
ql_output_path() / "Raw.qll": ql.DbClasses(),
|
||||
}
|
||||
|
||||
|
||||
@@ -192,10 +199,11 @@ def test_single_property(generate_classes):
|
||||
schema.SingleProperty("foo", "bar")]),
|
||||
]) == {
|
||||
"MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
|
||||
ql.Class(name="MyObject", final=True, properties=[
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects",
|
||||
tableparams=["this", "result"]),
|
||||
])),
|
||||
ql.Class(name="MyObject", final=True,
|
||||
properties=[
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects",
|
||||
tableparams=["this", "result"]),
|
||||
])),
|
||||
}
|
||||
|
||||
|
||||
@@ -208,14 +216,15 @@ def test_single_properties(generate_classes):
|
||||
]),
|
||||
]) == {
|
||||
"MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
|
||||
ql.Class(name="MyObject", final=True, properties=[
|
||||
ql.Property(singular="One", type="x", tablename="my_objects",
|
||||
tableparams=["this", "result", "_", "_"]),
|
||||
ql.Property(singular="Two", type="y", tablename="my_objects",
|
||||
tableparams=["this", "_", "result", "_"]),
|
||||
ql.Property(singular="Three", type="z", tablename="my_objects",
|
||||
tableparams=["this", "_", "_", "result"]),
|
||||
])),
|
||||
ql.Class(name="MyObject", final=True,
|
||||
properties=[
|
||||
ql.Property(singular="One", type="x", tablename="my_objects",
|
||||
tableparams=["this", "result", "_", "_"]),
|
||||
ql.Property(singular="Two", type="y", tablename="my_objects",
|
||||
tableparams=["this", "_", "result", "_"]),
|
||||
ql.Property(singular="Three", type="z", tablename="my_objects",
|
||||
tableparams=["this", "_", "_", "result"]),
|
||||
])),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ def load(tmp_path):
|
||||
|
||||
def test_empty_schema(load):
|
||||
ret = load("{}")
|
||||
assert ret.classes == [schema.Class(root_name)]
|
||||
assert ret.classes == {root_name: schema.Class(root_name)}
|
||||
assert ret.includes == set()
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@ def test_one_empty_class(load):
|
||||
ret = load("""
|
||||
MyClass: {}
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'MyClass'}),
|
||||
schema.Class('MyClass', bases={root_name}),
|
||||
]
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'MyClass'}),
|
||||
'MyClass': schema.Class('MyClass', bases={root_name}),
|
||||
}
|
||||
|
||||
|
||||
def test_two_empty_classes(load):
|
||||
@@ -39,11 +39,11 @@ def test_two_empty_classes(load):
|
||||
MyClass1: {}
|
||||
MyClass2: {}
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'MyClass1', 'MyClass2'}),
|
||||
schema.Class('MyClass1', bases={root_name}),
|
||||
schema.Class('MyClass2', bases={root_name}),
|
||||
]
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'MyClass1', 'MyClass2'}),
|
||||
'MyClass1': schema.Class('MyClass1', bases={root_name}),
|
||||
'MyClass2': schema.Class('MyClass2', bases={root_name}),
|
||||
}
|
||||
|
||||
|
||||
def test_two_empty_chained_classes(load):
|
||||
@@ -52,11 +52,11 @@ MyClass1: {}
|
||||
MyClass2:
|
||||
_extends: MyClass1
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'MyClass1'}),
|
||||
schema.Class('MyClass1', bases={root_name}, derived={'MyClass2'}),
|
||||
schema.Class('MyClass2', bases={'MyClass1'}),
|
||||
]
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'MyClass1'}),
|
||||
'MyClass1': schema.Class('MyClass1', bases={root_name}, derived={'MyClass2'}),
|
||||
'MyClass2': schema.Class('MyClass2', bases={'MyClass1'}),
|
||||
}
|
||||
|
||||
|
||||
def test_empty_classes_diamond(load):
|
||||
@@ -68,12 +68,12 @@ C:
|
||||
- A
|
||||
- B
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A', 'B'}),
|
||||
schema.Class('A', bases={root_name}, derived={'C'}),
|
||||
schema.Class('B', bases={root_name}, derived={'C'}),
|
||||
schema.Class('C', bases={'A', 'B'}),
|
||||
]
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A', 'B'}),
|
||||
'A': schema.Class('A', bases={root_name}, derived={'C'}),
|
||||
'B': schema.Class('B', bases={root_name}, derived={'C'}),
|
||||
'C': schema.Class('C', bases={'A', 'B'}),
|
||||
}
|
||||
|
||||
|
||||
def test_dir(load):
|
||||
@@ -81,10 +81,10 @@ def test_dir(load):
|
||||
A:
|
||||
_dir: other/dir
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, dir=pathlib.Path("other/dir")),
|
||||
]
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, dir=pathlib.Path("other/dir")),
|
||||
}
|
||||
|
||||
|
||||
def test_directory_filter(load):
|
||||
@@ -101,16 +101,16 @@ Ax: {}
|
||||
Ay: {}
|
||||
A: {}
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'Afoo', 'Bbar', 'Abar', 'Bfoo', 'Ax', 'Ay', 'A'}),
|
||||
schema.Class('Afoo', bases={root_name}, dir=pathlib.Path("second/dir")),
|
||||
schema.Class('Bbar', bases={root_name}, dir=pathlib.Path("third/dir")),
|
||||
schema.Class('Abar', bases={root_name}, dir=pathlib.Path("third/dir")),
|
||||
schema.Class('Bfoo', bases={root_name}, dir=pathlib.Path("second/dir")),
|
||||
schema.Class('Ax', bases={root_name}, dir=pathlib.Path("first/dir")),
|
||||
schema.Class('Ay', bases={root_name}, dir=pathlib.Path("first/dir")),
|
||||
schema.Class('A', bases={root_name}, dir=pathlib.Path()),
|
||||
]
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'Afoo', 'Bbar', 'Abar', 'Bfoo', 'Ax', 'Ay', 'A'}),
|
||||
'Afoo': schema.Class('Afoo', bases={root_name}, dir=pathlib.Path("second/dir")),
|
||||
'Bbar': schema.Class('Bbar', bases={root_name}, dir=pathlib.Path("third/dir")),
|
||||
'Abar': schema.Class('Abar', bases={root_name}, dir=pathlib.Path("third/dir")),
|
||||
'Bfoo': schema.Class('Bfoo', bases={root_name}, dir=pathlib.Path("second/dir")),
|
||||
'Ax': schema.Class('Ax', bases={root_name}, dir=pathlib.Path("first/dir")),
|
||||
'Ay': schema.Class('Ay', bases={root_name}, dir=pathlib.Path("first/dir")),
|
||||
'A': schema.Class('A', bases={root_name}, dir=pathlib.Path()),
|
||||
}
|
||||
|
||||
|
||||
def test_directory_filter_override(load):
|
||||
@@ -120,10 +120,10 @@ _directories:
|
||||
A:
|
||||
_dir: other/dir
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, dir=pathlib.Path("other/dir")),
|
||||
]
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, dir=pathlib.Path("other/dir")),
|
||||
}
|
||||
|
||||
|
||||
def test_lowercase_rejected(load):
|
||||
@@ -145,16 +145,16 @@ A:
|
||||
four: x?*
|
||||
five: predicate
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, properties=[
|
||||
schema.SingleProperty('one', 'string'),
|
||||
schema.OptionalProperty('two', 'int'),
|
||||
schema.RepeatedProperty('three', 'bool'),
|
||||
schema.RepeatedOptionalProperty('four', 'x'),
|
||||
schema.PredicateProperty('five'),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_element_properties(load):
|
||||
@@ -162,11 +162,11 @@ def test_element_properties(load):
|
||||
Element:
|
||||
x: string
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, properties=[
|
||||
schema.SingleProperty('x', 'string'),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_children(load):
|
||||
@@ -180,9 +180,9 @@ A:
|
||||
e: E?
|
||||
f: F?*
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, properties=[
|
||||
schema.SingleProperty('a', 'string'),
|
||||
schema.RepeatedProperty('b', 'B'),
|
||||
schema.SingleProperty('c', 'C', is_child=True),
|
||||
@@ -190,7 +190,7 @@ A:
|
||||
schema.OptionalProperty('e', 'E', is_child=True),
|
||||
schema.RepeatedOptionalProperty('f', 'F', is_child=True),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("type", ["string", "int", "boolean", "predicate"])
|
||||
@@ -209,12 +209,12 @@ A:
|
||||
x:
|
||||
type: string*
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, properties=[
|
||||
schema.RepeatedProperty('x', 'string'),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_property_with_explicit_type_and_pragmas(load):
|
||||
@@ -224,12 +224,12 @@ A:
|
||||
type: string*
|
||||
_pragma: [foo, bar]
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, properties=[
|
||||
schema.RepeatedProperty('x', 'string', pragmas=["foo", "bar"]),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_property_with_explicit_type_and_one_pragma(load):
|
||||
@@ -239,12 +239,12 @@ A:
|
||||
type: string*
|
||||
_pragma: foo
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, properties=[
|
||||
schema.RepeatedProperty('x', 'string', pragmas=["foo"]),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_property_with_explicit_type_and_unknown_metadata(load):
|
||||
@@ -272,12 +272,12 @@ A:
|
||||
x: string*
|
||||
_pragma: [foo, bar]
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, properties=[
|
||||
schema.RepeatedProperty('x', 'string'),
|
||||
], pragmas=["foo", "bar"]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_class_with_one_pragma(load):
|
||||
@@ -286,12 +286,12 @@ A:
|
||||
x: string*
|
||||
_pragma: foo
|
||||
""")
|
||||
assert ret.classes == [
|
||||
schema.Class(root_name, derived={'A'}),
|
||||
schema.Class('A', bases={root_name}, properties=[
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'A'}),
|
||||
'A': schema.Class('A', bases={root_name}, properties=[
|
||||
schema.RepeatedProperty('x', 'string'),
|
||||
], pragmas=["foo"]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_class_with_unknown_metadata(load):
|
||||
@@ -303,5 +303,34 @@ A:
|
||||
""")
|
||||
|
||||
|
||||
def test_ipa_class_from(load):
|
||||
ret = load("""
|
||||
MyClass:
|
||||
_synth:
|
||||
from: A
|
||||
""")
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'MyClass'}),
|
||||
'MyClass': schema.Class('MyClass', bases={root_name}, ipa=schema.IpaInfo(from_class="A")),
|
||||
}
|
||||
|
||||
|
||||
def test_ipa_class_on(load):
|
||||
ret = load("""
|
||||
MyClass:
|
||||
_synth:
|
||||
on:
|
||||
x: A
|
||||
y: int
|
||||
""")
|
||||
assert ret.classes == {
|
||||
root_name: schema.Class(root_name, derived={'MyClass'}),
|
||||
'MyClass': schema.Class('MyClass', bases={root_name}, ipa=schema.IpaInfo(on_arguments={"x": "A", "y": "int"})),
|
||||
}
|
||||
|
||||
|
||||
# TODO rejection tests and implementation for malformed `_synth` clauses
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(pytest.main([__file__] + sys.argv[1:]))
|
||||
|
||||
@@ -96,14 +96,6 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
|
||||
}
|
||||
TrapDomain trap{*trapTarget};
|
||||
|
||||
// TODO: remove this and recreate it with IPA when we have that
|
||||
// the following cannot conflict with actual files as those have an absolute path starting with /
|
||||
File unknownFileEntry{trap.createLabel<FileTag>("unknown")};
|
||||
Location unknownLocationEntry{trap.createLabel<LocationTag>("unknown")};
|
||||
unknownLocationEntry.file = unknownFileEntry.id;
|
||||
trap.emit(unknownFileEntry);
|
||||
trap.emit(unknownLocationEntry);
|
||||
|
||||
std::vector<swift::Token> comments;
|
||||
if (primaryFile && primaryFile->getBufferID().hasValue()) {
|
||||
auto& sourceManager = compiler.getSourceMgr();
|
||||
|
||||
@@ -258,13 +258,13 @@ class SwiftDispatcher {
|
||||
return;
|
||||
}
|
||||
auto file = getFilePath(sourceManager.getDisplayNameForLoc(start));
|
||||
Location entry{{}};
|
||||
DbLocation entry{{}};
|
||||
entry.file = fetchLabel(file);
|
||||
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
|
||||
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(end);
|
||||
entry.id = trap.createLabel<LocationTag>('{', entry.file, "}:", entry.start_line, ':',
|
||||
entry.start_column, ':', entry.end_line, ':',
|
||||
entry.end_column);
|
||||
entry.id = trap.createLabel<DbLocationTag>('{', entry.file, "}:", entry.start_line, ':',
|
||||
entry.start_column, ':', entry.end_line, ':',
|
||||
entry.end_column);
|
||||
emit(entry);
|
||||
emit(LocatableLocationsTrap{locatableLabel, entry.id});
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ MAP_TYPE_TO_TAG(swift::TypeBase, TypeTag);
|
||||
OVERRIDE_TAG(FuncDecl, ConcreteFuncDeclTag);
|
||||
OVERRIDE_TAG(VarDecl, ConcreteVarDeclTag);
|
||||
|
||||
MAP_TYPE_TO_TAG(FilePath, FileTag);
|
||||
MAP_TYPE_TO_TAG(FilePath, DbFileTag);
|
||||
|
||||
#undef MAP_TAG
|
||||
#undef MAP_SUBTAG
|
||||
|
||||
@@ -6,6 +6,8 @@ private import internal.ControlFlowGraphImpl
|
||||
private import internal.ControlFlowElements
|
||||
private import CfgNodes
|
||||
private import SuccessorTypes
|
||||
private import codeql.swift.generated.Raw
|
||||
private import codeql.swift.generated.Synth
|
||||
|
||||
/**
|
||||
* A basic block, that is, a maximal straight-line sequence of control flow nodes
|
||||
@@ -195,11 +197,14 @@ class ExitBasicBlock extends BasicBlock {
|
||||
}
|
||||
|
||||
private module JoinBlockPredecessors {
|
||||
private predicate id(AstNode x, AstNode y) { x = y }
|
||||
private predicate id(Raw::AstNode x, Raw::AstNode y) { x = y }
|
||||
|
||||
private predicate idOf(AstNode x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
private predicate idOfDbAstNode(Raw::AstNode x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
|
||||
private AstNode projctToAst(ControlFlowElement n) {
|
||||
// TODO does not work if fresh ipa entities (`ipa: on:`) turn out to be first of the block
|
||||
private predicate idOf(AstNode x, int y) { idOfDbAstNode(Synth::convertAstNodeToRaw(x), y) }
|
||||
|
||||
private AstNode projectToAst(ControlFlowElement n) {
|
||||
result = n.asAstNode()
|
||||
or
|
||||
isPropertyGetterElement(n, _, result)
|
||||
@@ -214,7 +219,7 @@ private module JoinBlockPredecessors {
|
||||
}
|
||||
|
||||
int getId(JoinBlockPredecessor jbp) {
|
||||
idOf(projctToAst(jbp.getFirstNode().(CfgNode).getNode()), result)
|
||||
idOf(projectToAst(jbp.getFirstNode().(CfgNode).getNode()), result)
|
||||
or
|
||||
idOf(jbp.(EntryBasicBlock).getScope(), result)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
private import swift
|
||||
private import codeql.swift.controlflow.ControlFlowGraph
|
||||
private import codeql.swift.generated.Synth
|
||||
private import Completion
|
||||
private import Scope
|
||||
import ControlFlowGraphImplShared
|
||||
@@ -379,9 +380,9 @@ module Stmts {
|
||||
* Control-flow for loops.
|
||||
*/
|
||||
module Loops {
|
||||
class ConditionalLoop = @while_stmt or @repeat_while_stmt;
|
||||
class ConditionalLoop = Synth::TWhileStmt or Synth::TRepeatWhileStmt;
|
||||
|
||||
class LoopStmt = @for_each_stmt or ConditionalLoop;
|
||||
class LoopStmt = Synth::TForEachStmt or ConditionalLoop;
|
||||
|
||||
abstract class LoopTree extends AstPreOrderTree {
|
||||
LoopTree() { ast instanceof ConditionalLoop }
|
||||
@@ -1706,7 +1707,8 @@ module Exprs {
|
||||
}
|
||||
|
||||
module Conversions {
|
||||
class ConversionOrIdentity = @identity_expr or @explicit_cast_expr or @implicit_conversion_expr;
|
||||
class ConversionOrIdentity =
|
||||
Synth::TIdentityExpr or Synth::TExplicitCastExpr or Synth::TImplicitConversionExpr;
|
||||
|
||||
abstract class ConversionOrIdentityTree extends AstStandardPostOrderTree {
|
||||
ConversionOrIdentityTree() { ast instanceof ConversionOrIdentity }
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
private import swift
|
||||
private import codeql.swift.generated.GetImmediateParent
|
||||
private import codeql.swift.generated.Synth
|
||||
|
||||
module CallableBase {
|
||||
class TypeRange = @abstract_function_decl or @key_path_expr or @closure_expr;
|
||||
class TypeRange = Synth::TAbstractFunctionDecl or Synth::TKeyPathExpr or Synth::TClosureExpr;
|
||||
|
||||
class Range extends Scope::Range, TypeRange { }
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
import codeql.swift.elements.AstNode
|
||||
import codeql.swift.elements.Callable
|
||||
import codeql.swift.elements.Comment
|
||||
import codeql.swift.elements.DbFile
|
||||
import codeql.swift.elements.DbLocation
|
||||
import codeql.swift.elements.Element
|
||||
import codeql.swift.elements.File
|
||||
import codeql.swift.elements.Locatable
|
||||
import codeql.swift.elements.Location
|
||||
import codeql.swift.elements.UnknownFile
|
||||
import codeql.swift.elements.UnknownLocation
|
||||
import codeql.swift.elements.decl.AbstractFunctionDecl
|
||||
import codeql.swift.elements.decl.AbstractStorageDecl
|
||||
import codeql.swift.elements.decl.AbstractTypeParamDecl
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructComment(Raw::Comment id) { any() }
|
||||
4
swift/ql/lib/codeql/swift/elements/DbFile.qll
Normal file
4
swift/ql/lib/codeql/swift/elements/DbFile.qll
Normal file
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.DbFile
|
||||
|
||||
class DbFile extends DbFileBase { }
|
||||
4
swift/ql/lib/codeql/swift/elements/DbFileConstructor.qll
Normal file
4
swift/ql/lib/codeql/swift/elements/DbFileConstructor.qll
Normal file
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDbFile(Raw::DbFile id) { any() }
|
||||
4
swift/ql/lib/codeql/swift/elements/DbLocation.qll
Normal file
4
swift/ql/lib/codeql/swift/elements/DbLocation.qll
Normal file
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.DbLocation
|
||||
|
||||
class DbLocation extends DbLocationBase { }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDbLocation(Raw::DbLocation id) { any() }
|
||||
@@ -4,9 +4,6 @@ class File extends FileBase {
|
||||
/** toString */
|
||||
override string toString() { result = getAbsolutePath() }
|
||||
|
||||
/** Gets the name of this file. */
|
||||
override string getName() { files(this, result) }
|
||||
|
||||
/** Gets the absolute path of this file. */
|
||||
string getAbsolutePath() { result = getName() }
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
private import codeql.swift.generated.Locatable
|
||||
private import codeql.swift.elements.File
|
||||
private import codeql.swift.elements.UnknownLocation
|
||||
|
||||
class Locatable extends LocatableBase {
|
||||
pragma[nomagic]
|
||||
override Location getLocation() {
|
||||
result = LocatableBase.super.getLocation()
|
||||
override Location getImmediateLocation() {
|
||||
result = LocatableBase.super.getImmediateLocation()
|
||||
or
|
||||
not exists(LocatableBase.super.getLocation()) and result instanceof UnknownLocation
|
||||
not exists(LocatableBase.super.getImmediateLocation()) and result instanceof UnknownLocation
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,3 @@ class Location extends LocationBase {
|
||||
ec = getEndColumn()
|
||||
}
|
||||
}
|
||||
|
||||
class UnknownLocation extends Location {
|
||||
UnknownLocation() { hasLocationInfo("", 0, 0, 0, 0) }
|
||||
}
|
||||
|
||||
5
swift/ql/lib/codeql/swift/elements/UnknownFile.qll
Normal file
5
swift/ql/lib/codeql/swift/elements/UnknownFile.qll
Normal file
@@ -0,0 +1,5 @@
|
||||
private import codeql.swift.generated.UnknownFile
|
||||
|
||||
class UnknownFile extends UnknownFileBase {
|
||||
override string getName() { result = "" }
|
||||
}
|
||||
15
swift/ql/lib/codeql/swift/elements/UnknownLocation.qll
Normal file
15
swift/ql/lib/codeql/swift/elements/UnknownLocation.qll
Normal file
@@ -0,0 +1,15 @@
|
||||
private import codeql.swift.generated.UnknownLocation
|
||||
private import codeql.swift.elements.UnknownFile
|
||||
private import codeql.swift.elements.File
|
||||
|
||||
class UnknownLocation extends UnknownLocationBase {
|
||||
override File getImmediateFile() { result instanceof UnknownFile }
|
||||
|
||||
override int getStartLine() { result = 0 }
|
||||
|
||||
override int getStartColumn() { result = 0 }
|
||||
|
||||
override int getEndLine() { result = 0 }
|
||||
|
||||
override int getEndColumn() { result = 0 }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructUnknownLocation() { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructAccessorDecl(Raw::AccessorDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructAssociatedTypeDecl(Raw::AssociatedTypeDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructClassDecl(Raw::ClassDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructConcreteFuncDecl(Raw::ConcreteFuncDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructConcreteVarDecl(Raw::ConcreteVarDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructConstructorDecl(Raw::ConstructorDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDestructorDecl(Raw::DestructorDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructEnumCaseDecl(Raw::EnumCaseDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructEnumDecl(Raw::EnumDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructEnumElementDecl(Raw::EnumElementDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructExtensionDecl(Raw::ExtensionDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructGenericTypeParamDecl(Raw::GenericTypeParamDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructIfConfigClause(Raw::IfConfigClause id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructIfConfigDecl(Raw::IfConfigDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructImportDecl(Raw::ImportDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructInfixOperatorDecl(Raw::InfixOperatorDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructMissingMemberDecl(Raw::MissingMemberDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructModuleDecl(Raw::ModuleDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructOpaqueTypeDecl(Raw::OpaqueTypeDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructParamDecl(Raw::ParamDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructPatternBindingDecl(Raw::PatternBindingDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructPostfixOperatorDecl(Raw::PostfixOperatorDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructPoundDiagnosticDecl(Raw::PoundDiagnosticDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructPrecedenceGroupDecl(Raw::PrecedenceGroupDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructPrefixOperatorDecl(Raw::PrefixOperatorDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructProtocolDecl(Raw::ProtocolDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructStructDecl(Raw::StructDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructSubscriptDecl(Raw::SubscriptDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructTopLevelCodeDecl(Raw::TopLevelCodeDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructTypeAliasDecl(Raw::TypeAliasDecl id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructAnyHashableErasureExpr(Raw::AnyHashableErasureExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructAppliedPropertyWrapperExpr(Raw::AppliedPropertyWrapperExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructArchetypeToSuperExpr(Raw::ArchetypeToSuperExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructArgument(Raw::Argument id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructArrayExpr(Raw::ArrayExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructArrayToPointerExpr(Raw::ArrayToPointerExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructArrowExpr(Raw::ArrowExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructAssignExpr(Raw::AssignExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructAutoClosureExpr(Raw::AutoClosureExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructAwaitExpr(Raw::AwaitExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructBinaryExpr(Raw::BinaryExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructBindOptionalExpr(Raw::BindOptionalExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructBooleanLiteralExpr(Raw::BooleanLiteralExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructBridgeFromObjCExpr(Raw::BridgeFromObjCExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructBridgeToObjCExpr(Raw::BridgeToObjCExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructCallExpr(Raw::CallExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructCaptureListExpr(Raw::CaptureListExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructClassMetatypeToObjectExpr(Raw::ClassMetatypeToObjectExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructClosureExpr(Raw::ClosureExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructCodeCompletionExpr(Raw::CodeCompletionExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructCoerceExpr(Raw::CoerceExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructCollectionUpcastConversionExpr(Raw::CollectionUpcastConversionExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructConditionalBridgeFromObjCExpr(Raw::ConditionalBridgeFromObjCExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructConditionalCheckedCastExpr(Raw::ConditionalCheckedCastExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructConstructorRefCallExpr(Raw::ConstructorRefCallExpr id) { any() }
|
||||
@@ -0,0 +1,6 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructCovariantFunctionConversionExpr(Raw::CovariantFunctionConversionExpr id) {
|
||||
any()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructCovariantReturnConversionExpr(Raw::CovariantReturnConversionExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDeclRefExpr(Raw::DeclRefExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDefaultArgumentExpr(Raw::DefaultArgumentExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDerivedToBaseExpr(Raw::DerivedToBaseExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDestructureTupleExpr(Raw::DestructureTupleExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDictionaryExpr(Raw::DictionaryExpr id) { any() }
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDifferentiableFunctionExpr(Raw::DifferentiableFunctionExpr id) { any() }
|
||||
@@ -0,0 +1,8 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDifferentiableFunctionExtractOriginalExpr(
|
||||
Raw::DifferentiableFunctionExtractOriginalExpr id
|
||||
) {
|
||||
any()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructDiscardAssignmentExpr(Raw::DiscardAssignmentExpr id) { any() }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user