mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Swift: allow skipping fields in cppgen
Some fields of base classes pose some problems with diamond hierarchies, and we don't use them any way as we are emitting them using directly trap entries instead of structured C++ classes. This introduces a `cpp_skip` pragma to skip generation of those fields in structured generated C++ classes, and applies it to `is_unknown` and `location`.
This commit is contained in:
@@ -13,6 +13,7 @@ Each class in the schema gets a corresponding `struct` in `TrapClasses.h`, where
|
||||
|
||||
import functools
|
||||
import pathlib
|
||||
import typing
|
||||
from typing import Dict
|
||||
|
||||
import inflection
|
||||
@@ -34,22 +35,25 @@ def _get_type(t: str) -> str:
|
||||
return t
|
||||
|
||||
|
||||
def _get_field(cls: schema.Class, p: schema.Property) -> cpp.Field:
|
||||
trap_name = None
|
||||
if not p.is_single:
|
||||
trap_name = inflection.camelize(f"{cls.name}_{p.name}")
|
||||
if not p.is_predicate:
|
||||
trap_name = inflection.pluralize(trap_name)
|
||||
args = dict(
|
||||
field_name=p.name + ("_" if p.name in cpp.cpp_keywords else ""),
|
||||
type=_get_type(p.type),
|
||||
is_optional=p.is_optional,
|
||||
is_repeated=p.is_repeated,
|
||||
is_predicate=p.is_predicate,
|
||||
trap_name=trap_name,
|
||||
)
|
||||
args.update(cpp.get_field_override(p.name))
|
||||
return cpp.Field(**args)
|
||||
def _get_fields(cls: schema.Class) -> typing.Iterable[cpp.Field]:
|
||||
for p in cls.properties:
|
||||
if "cpp_skip" in p.pragmas:
|
||||
continue
|
||||
trap_name = None
|
||||
if not p.is_single:
|
||||
trap_name = inflection.camelize(f"{cls.name}_{p.name}")
|
||||
if not p.is_predicate:
|
||||
trap_name = inflection.pluralize(trap_name)
|
||||
args = dict(
|
||||
field_name=p.name + ("_" if p.name in cpp.cpp_keywords else ""),
|
||||
type=_get_type(p.type),
|
||||
is_optional=p.is_optional,
|
||||
is_repeated=p.is_repeated,
|
||||
is_predicate=p.is_predicate,
|
||||
trap_name=trap_name,
|
||||
)
|
||||
args.update(cpp.get_field_override(p.name))
|
||||
yield cpp.Field(**args)
|
||||
|
||||
|
||||
class Processor:
|
||||
@@ -65,7 +69,7 @@ class Processor:
|
||||
return cpp.Class(
|
||||
name=name,
|
||||
bases=[self._get_class(b) for b in cls.bases],
|
||||
fields=[_get_field(cls, p) for p in cls.properties],
|
||||
fields=list(_get_fields(cls)),
|
||||
final=not cls.derived,
|
||||
trap_name=trap_name,
|
||||
)
|
||||
|
||||
@@ -13,14 +13,18 @@ _directories:
|
||||
stmt: Stmt$
|
||||
|
||||
Element:
|
||||
is_unknown: predicate
|
||||
is_unknown:
|
||||
type: predicate
|
||||
_pragma: cpp_skip # this is emitted using trap entries directly
|
||||
_pragma: qltest_skip
|
||||
|
||||
File:
|
||||
name: string
|
||||
|
||||
Locatable:
|
||||
location: Location?
|
||||
location:
|
||||
type: Location?
|
||||
_pragma: cpp_skip # this is emitted using trap entries directly
|
||||
_pragma: qltest_skip
|
||||
|
||||
Location:
|
||||
|
||||
@@ -165,5 +165,18 @@ def test_classes_with_dirs(generate_grouped):
|
||||
}
|
||||
|
||||
|
||||
def test_cpp_skip_pragma(generate):
|
||||
assert generate([
|
||||
schema.Class(name="A", properties=[
|
||||
schema.SingleProperty("x", "foo"),
|
||||
schema.SingleProperty("y", "bar", pragmas=["x", "cpp_skip", "y"]),
|
||||
])
|
||||
]) == [
|
||||
cpp.Class(name="A", final=True, trap_name="As", fields=[
|
||||
cpp.Field("x", "foo"),
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(pytest.main([__file__] + sys.argv[1:]))
|
||||
|
||||
Reference in New Issue
Block a user