Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codegen/Rust: allow renaming in QL #18094

Merged
merged 3 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions misc/codegen/generators/qlgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,32 +118,33 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
type_is_hideable="ql_hideable" in lookup[prop.type].pragmas if prop.type in lookup else False,
internal="ql_internal" in prop.pragmas,
)
ql_name = prop.pragmas.get("ql_name", prop.name)
if prop.is_single:
args.update(
singular=inflection.camelize(prop.name),
singular=inflection.camelize(ql_name),
tablename=inflection.tableize(cls.name),
tableparams=["this"] + ["result" if p is prop else "_" for p in cls.properties if p.is_single],
doc=_get_doc(cls, prop),
)
elif prop.is_repeated:
args.update(
singular=inflection.singularize(inflection.camelize(prop.name)),
plural=inflection.pluralize(inflection.camelize(prop.name)),
singular=inflection.singularize(inflection.camelize(ql_name)),
plural=inflection.pluralize(inflection.camelize(ql_name)),
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
tableparams=["this", "index", "result"] if not prop.is_unordered else ["this", "result"],
doc=_get_doc(cls, prop, plural=False),
doc_plural=_get_doc(cls, prop, plural=True),
)
elif prop.is_optional:
args.update(
singular=inflection.camelize(prop.name),
singular=inflection.camelize(ql_name),
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
tableparams=["this", "result"],
doc=_get_doc(cls, prop),
)
elif prop.is_predicate:
args.update(
singular=inflection.camelize(prop.name, uppercase_first_letter=False),
singular=inflection.camelize(ql_name, uppercase_first_letter=False),
tablename=inflection.underscore(f"{cls.name}_{prop.name}"),
tableparams=["this"],
doc=_get_doc(cls, prop),
Expand All @@ -154,6 +155,8 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic


def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> ql.Class:
if "ql_name" in cls.pragmas:
raise Error("ql_name is not supported yet for classes, only for properties")
prev_child = ""
properties = []
for p in cls.properties:
Expand Down
27 changes: 11 additions & 16 deletions misc/codegen/lib/schemadefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ def include(source: str):
@_dataclass
class _Namespace:
""" simple namespacing mechanism """
name: str
_name: str

def add(self, pragma: "_PragmaBase", key: str | None = None):
self.__dict__[pragma.pragma] = pragma
pragma.pragma = key or f"{self.name}_{pragma.pragma}"
pragma.pragma = key or f"{self._name}_{pragma.pragma}"


@_dataclass
Expand All @@ -87,7 +87,7 @@ def modify(self, prop: _schema.Property):
prop.synth = self.synth

def negate(self) -> _schema.PropertyModifier:
return _SynthModifier(self.name, False)
return _SynthModifier(self._name, False)


qltest = _Namespace("qltest")
Expand Down Expand Up @@ -239,6 +239,7 @@ def __getitem__(self, item):
ql.add(_ParametrizedClassPragma("default_doc_name", factory=lambda doc: doc))
ql.add(_ClassPragma("hideable", inherited=True))
ql.add(_Pragma("internal"))
ql.add(_ParametrizedPragma("name", factory=lambda name: name))

cpp.add(_Pragma("skip"))

Expand All @@ -256,38 +257,32 @@ def __getitem__(self, item):
_schema.SynthInfo(on_arguments={k: _schema.get_type_name(t) for k, t in kwargs.items()})), key="synth")


@_dataclass(frozen=True)
class _PropertyModifierList(_schema.PropertyModifier):
def __init__(self):
self._mods = []
_mods: tuple[_schema.PropertyModifier, ...]

def __or__(self, other: _schema.PropertyModifier):
self._mods.append(other)
return self
return _PropertyModifierList(self._mods + (other,))

def modify(self, prop: Property):
for m in self._mods:
m.modify(prop)


class _PropertyAnnotation:
def __or__(self, other: _schema.PropertyModifier):
return _PropertyModifierList() | other


_ = _PropertyAnnotation()
_ = _PropertyModifierList(())

drop = object()


def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None, cfg: bool = False) -> _Callable[[type], _PropertyAnnotation]:
def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None, cfg: bool = False) -> _Callable[[type], _PropertyModifierList]:
"""
Add or modify schema annotations after a class has been defined previously.

The name of the class used for annotation must be `_`.

`replace_bases` can be used to replace bases on the annotated class.
"""
def decorator(cls: type) -> _PropertyAnnotation:
def decorator(cls: type) -> _PropertyModifierList:
if cls.__name__ != "_":
raise _schema.Error("Annotation classes must be named _")
if cls.__doc__ is not None:
Expand All @@ -307,7 +302,7 @@ def decorator(cls: type) -> _PropertyAnnotation:
del annotated_cls.__annotations__[p]
elif p in annotated_cls.__annotations__:
annotated_cls.__annotations__[p] |= a
elif isinstance(a, (_PropertyAnnotation, _PropertyModifierList)):
elif isinstance(a, (_PropertyModifierList, _PropertyModifierList)):
raise _schema.Error(f"annotated property {p} not present in annotated class "
f"{annotated_cls.__name__}")
else:
Expand Down
12 changes: 6 additions & 6 deletions rust/ql/.generated.list

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust/ql/.gitattributes

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -514,14 +514,14 @@ module ExprTrees {

class MatchExprTree extends PostOrderTree instanceof MatchExpr {
override predicate propagatesAbnormal(AstNode child) {
child = [super.getExpr(), super.getAnArm().getExpr()]
child = [super.getMatchedExpr(), super.getAnArm().getExpr()]
}

override predicate first(AstNode node) { first(super.getExpr(), node) }
override predicate first(AstNode node) { first(super.getMatchedExpr(), node) }

override predicate succ(AstNode pred, AstNode succ, Completion c) {
// Edge from the scrutinee to the first arm or to the match expression if no arms.
last(super.getExpr(), pred, c) and
last(super.getMatchedExpr(), pred, c) and
(
first(super.getArm(0).getPat(), succ)
or
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| gen_match_expr.rs:5:5:8:5 | match x { ... } | getNumberOfAttrs: | 0 | hasExpr: | yes | hasMatchArmList: | yes |
| gen_match_expr.rs:9:5:12:5 | match x { ... } | getNumberOfAttrs: | 0 | hasExpr: | yes | hasMatchArmList: | yes |
| gen_match_expr.rs:5:5:8:5 | match x { ... } | getNumberOfAttrs: | 0 | hasMatched: | yes | hasMatchArmList: | yes |
| gen_match_expr.rs:9:5:12:5 | match x { ... } | getNumberOfAttrs: | 0 | hasMatched: | yes | hasMatchArmList: | yes |
Loading
Loading