Merge pull request #19063 from github/redsun82/codegen-rename-dbscheme

Codegen: add `ql.db_table_name` property pragma
This commit is contained in:
Paolo Tranquilli
2025-03-31 12:01:35 +02:00
committed by GitHub
37 changed files with 347 additions and 140 deletions

View File

@@ -37,5 +37,6 @@ build --java_language_version=17
build --tool_java_language_version=17
build --tool_java_runtime_version=remotejdk_17
build --java_runtime_version=remotejdk_17
build --@rules_python//python/config_settings:python_version=3.12
try-import %workspace%/local.bazelrc

View File

@@ -8,3 +8,5 @@ common --registry=https://bcr.bazel.build
# its implementation packages without providing any code itself.
# We either can depend on internal implementation details, or turn of strict deps.
common --@rules_dotnet//dotnet/settings:strict_deps=false
build --@rules_python//python/config_settings:python_version=3.12

View File

@@ -155,7 +155,7 @@ use_repo(csharp_main_extension, "paket.main")
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
hub_name = "codegen_deps",
python_version = "3.11",
python_version = "3.12",
requirements_lock = "//misc/codegen:requirements_lock.txt",
)
use_repo(pip, "codegen_deps")

View File

@@ -1 +1 @@
3.11
3.12

View File

@@ -37,12 +37,19 @@ def _get_type(t: str, add_or_none_except: typing.Optional[str] = None) -> str:
return t
def _get_field(cls: schema.Class, p: schema.Property, add_or_none_except: typing.Optional[str] = None) -> cpp.Field:
trap_name = None
if not p.is_single:
def _get_trap_name(cls: schema.Class, p: schema.Property) -> str | None:
if p.is_single:
return None
overridden_trap_name = p.pragmas.get("ql_db_table_name")
if overridden_trap_name:
return inflection.camelize(overridden_trap_name)
trap_name = inflection.camelize(f"{cls.name}_{p.name}")
if not p.is_predicate:
trap_name = inflection.pluralize(trap_name)
if p.is_predicate:
return trap_name
return inflection.pluralize(trap_name)
def _get_field(cls: schema.Class, p: schema.Property, add_or_none_except: typing.Optional[str] = None) -> cpp.Field:
args = dict(
field_name=p.name + ("_" if p.name in cpp.cpp_keywords else ""),
base_type=_get_type(p.type, add_or_none_except),
@@ -50,7 +57,7 @@ def _get_field(cls: schema.Class, p: schema.Property, add_or_none_except: typing
is_repeated=p.is_repeated,
is_predicate=p.is_predicate,
is_unordered=p.is_unordered,
trap_name=trap_name,
trap_name=_get_trap_name(cls, p),
)
args.update(cpp.get_field_override(p.name))
return cpp.Field(**args)

View File

@@ -24,6 +24,10 @@ from misc.codegen.lib.dbscheme import *
log = logging.getLogger(__name__)
class Error(Exception):
pass
def dbtype(typename: str, add_or_none_except: typing.Optional[str] = None) -> str:
""" translate a type to a dbscheme counterpart, using `@lower_underscore` format for classes.
For class types, appends an underscore followed by `null` if provided
@@ -65,11 +69,12 @@ def cls_to_dbscheme(cls: schema.Class, lookup: typing.Dict[str, schema.Class], a
)
# use property-specific tables for 1-to-many and 1-to-at-most-1 properties
for f in cls.properties:
overridden_table_name = f.pragmas.get("ql_db_table_name")
if f.synth:
continue
if f.is_unordered:
yield Table(
name=inflection.tableize(f"{cls.name}_{f.name}"),
name=overridden_table_name or inflection.tableize(f"{cls.name}_{f.name}"),
columns=[
Column("id", type=dbtype(cls.name)),
Column(inflection.singularize(f.name), dbtype(f.type, add_or_none_except)),
@@ -79,7 +84,7 @@ def cls_to_dbscheme(cls: schema.Class, lookup: typing.Dict[str, schema.Class], a
elif f.is_repeated:
yield Table(
keyset=KeySet(["id", "index"]),
name=inflection.tableize(f"{cls.name}_{f.name}"),
name=overridden_table_name or inflection.tableize(f"{cls.name}_{f.name}"),
columns=[
Column("id", type=dbtype(cls.name)),
Column("index", type="int"),
@@ -90,7 +95,7 @@ def cls_to_dbscheme(cls: schema.Class, lookup: typing.Dict[str, schema.Class], a
elif f.is_optional:
yield Table(
keyset=KeySet(["id"]),
name=inflection.tableize(f"{cls.name}_{f.name}"),
name=overridden_table_name or inflection.tableize(f"{cls.name}_{f.name}"),
columns=[
Column("id", type=dbtype(cls.name)),
Column(f.name, dbtype(f.type, add_or_none_except)),
@@ -100,7 +105,7 @@ def cls_to_dbscheme(cls: schema.Class, lookup: typing.Dict[str, schema.Class], a
elif f.is_predicate:
yield Table(
keyset=KeySet(["id"]),
name=inflection.underscore(f"{cls.name}_{f.name}"),
name=overridden_table_name or inflection.underscore(f"{cls.name}_{f.name}"),
columns=[
Column("id", type=dbtype(cls.name)),
],
@@ -108,6 +113,17 @@ def cls_to_dbscheme(cls: schema.Class, lookup: typing.Dict[str, schema.Class], a
)
def check_name_conflicts(decls: list[Table | Union]):
names = set()
for decl in decls:
match decl:
case Table(name=name):
if name in names:
raise Error(f"Duplicate table name: {
name}, you can use `@ql.db_table_name` on a property to resolve this")
names.add(name)
def get_declarations(data: schema.Schema):
add_or_none_except = data.root_class.name if data.null else None
declarations = [d for cls in data.classes.values() if not cls.imported for d in cls_to_dbscheme(cls,
@@ -120,6 +136,7 @@ def get_declarations(data: schema.Schema):
declarations += [
Union(dbtype(t, data.null), [dbtype(t), dbtype(data.null)]) for t in sorted(property_classes)
]
check_name_conflicts(declarations)
return declarations

View File

@@ -130,6 +130,9 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
internal="ql_internal" in prop.pragmas,
)
ql_name = prop.pragmas.get("ql_name", prop.name)
db_table_name = prop.pragmas.get("ql_db_table_name")
if db_table_name and prop.is_single:
raise Error(f"`db_table_name` pragma is not supported for single properties, but {cls.name}.{prop.name} has it")
if prop.is_single:
args.update(
singular=inflection.camelize(ql_name),
@@ -141,7 +144,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
args.update(
singular=inflection.singularize(inflection.camelize(ql_name)),
plural=inflection.pluralize(inflection.camelize(ql_name)),
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
tablename=db_table_name or 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),
@@ -149,14 +152,14 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
elif prop.is_optional:
args.update(
singular=inflection.camelize(ql_name),
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
tablename=db_table_name or inflection.tableize(f"{cls.name}_{prop.name}"),
tableparams=["this", "result"],
doc=_get_doc(cls, prop),
)
elif prop.is_predicate:
args.update(
singular=inflection.camelize(ql_name, uppercase_first_letter=False),
tablename=inflection.underscore(f"{cls.name}_{prop.name}"),
tablename=db_table_name or inflection.underscore(f"{cls.name}_{prop.name}"),
tableparams=["this"],
doc=_get_doc(cls, prop),
)

View File

@@ -27,14 +27,20 @@ def _get_type(t: str) -> str:
return t
def _get_field(cls: schema.Class, p: schema.Property) -> rust.Field:
table_name = inflection.tableize(cls.name)
if not p.is_single:
def _get_table_name(cls: schema.Class, p: schema.Property) -> str:
if p.is_single:
return inflection.tableize(cls.name)
overridden_table_name = p.pragmas.get("ql_db_table_name")
if overridden_table_name:
return overridden_table_name
table_name = f"{cls.name}_{p.name}"
if p.is_predicate:
table_name = inflection.underscore(table_name)
return inflection.underscore(table_name)
else:
table_name = inflection.tableize(table_name)
return inflection.tableize(table_name)
def _get_field(cls: schema.Class, p: schema.Property) -> rust.Field:
args = dict(
field_name=rust.avoid_keywords(p.name),
base_type=_get_type(p.type),
@@ -42,7 +48,7 @@ def _get_field(cls: schema.Class, p: schema.Property) -> rust.Field:
is_repeated=p.is_repeated,
is_predicate=p.is_predicate,
is_unordered=p.is_unordered,
table_name=table_name,
table_name=_get_table_name(cls, p),
)
args.update(rust.get_field_override(p.name))
return rust.Field(**args)

View File

@@ -2,8 +2,9 @@ from typing import (
Callable as _Callable,
Dict as _Dict,
Iterable as _Iterable,
ClassVar as _ClassVar,
Union as _Union,
)
from copy import deepcopy as _deepcopy
from misc.codegen.lib import schema as _schema
import inspect as _inspect
from dataclasses import dataclass as _dataclass
@@ -75,7 +76,7 @@ class _Namespace:
""" simple namespacing mechanism """
_name: str
def add(self, pragma: "_PragmaBase", key: str | None = None):
def add(self, pragma: _Union["_PragmaBase", "_Parametrized"], key: str | None = None):
self.__dict__[pragma.pragma] = pragma
pragma.pragma = key or f"{self._name}_{pragma.pragma}"
@@ -101,6 +102,10 @@ synth = _SynthModifier("synth")
@_dataclass
class _PragmaBase:
pragma: str
value: object = None
def _apply(self, pragmas: _Dict[str, object]) -> None:
pragmas[self.pragma] = self.value
@_dataclass
@@ -109,7 +114,6 @@ class _ClassPragma(_PragmaBase):
For schema classes it acts as a python decorator with `@`.
"""
inherited: bool = False
value: object = None
def __call__(self, cls: type) -> type:
""" use this pragma as a decorator on classes """
@@ -122,15 +126,11 @@ class _ClassPragma(_PragmaBase):
self._apply(cls._pragmas)
return cls
def _apply(self, pragmas: _Dict[str, object]) -> None:
pragmas[self.pragma] = self.value
@_dataclass
class _Pragma(_ClassPragma, _schema.PropertyModifier):
""" A class or property pragma.
For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma.
For schema classes it acts as a python decorator with `@`.
class _PropertyPragma(_PragmaBase, _schema.PropertyModifier):
""" A property pragma.
It functions similarly to a `_PropertyModifier` with `|`, adding the pragma.
"""
remove: bool = False
@@ -138,7 +138,7 @@ class _Pragma(_ClassPragma, _schema.PropertyModifier):
self._apply(prop.pragmas)
def negate(self) -> _schema.PropertyModifier:
return _Pragma(self.pragma, remove=True)
return _PropertyPragma(self.pragma, remove=not self.remove)
def _apply(self, pragmas: _Dict[str, object]) -> None:
if self.remove:
@@ -148,31 +148,38 @@ class _Pragma(_ClassPragma, _schema.PropertyModifier):
@_dataclass
class _ParametrizedClassPragma(_PragmaBase):
""" A class parametrized pragma.
Needs to be applied to a parameter to give a class pragma.
class _Pragma(_ClassPragma, _PropertyPragma):
""" A class or property pragma.
For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma.
For schema classes it acts as a python decorator with `@`.
"""
_pragma_class: _ClassVar[type] = _ClassPragma
inherited: bool = False
factory: _Callable[..., object] = None
def __post_init__(self):
self.__signature__ = _inspect.signature(self.factory).replace(return_annotation=self._pragma_class)
def __call__(self, *args, **kwargs) -> _pragma_class:
return self._pragma_class(self.pragma, self.inherited, value=self.factory(*args, **kwargs))
@_dataclass
class _ParametrizedPragma(_ParametrizedClassPragma):
""" A class or property parametrized pragma.
class _Parametrized[P, **Q, T]:
""" A parametrized pragma.
Needs to be applied to a parameter to give a pragma.
"""
_pragma_class: _ClassVar[type] = _Pragma
def __invert__(self) -> _Pragma:
return _Pragma(self.pragma, remove=True)
def __init__(self, pragma_instance: P, factory: _Callable[Q, T]):
self.pragma_instance = pragma_instance
self.factory = factory
self.__signature__ = _inspect.signature(self.factory).replace(return_annotation=type(self.pragma_instance))
@property
def pragma(self):
return self.pragma_instance.pragma
@pragma.setter
def pragma(self, value):
self.pragma_instance.pragma = value
def __invert__(self) -> "_Parametrized[P, Q, T]":
return _Parametrized(~self.pragma_instance, factory=self.factory)
def __call__(self, *args: Q.args, **kwargs: Q.kwargs) -> T:
ret = _deepcopy(self.pragma_instance)
ret.value = self.factory(*args, **kwargs)
return ret
class _Optionalizer(_schema.PropertyModifier):
@@ -232,29 +239,30 @@ desc = _DescModifier
use_for_null = _ClassPragma("null")
qltest.add(_Pragma("skip"))
qltest.add(_ClassPragma("skip"))
qltest.add(_ClassPragma("collapse_hierarchy"))
qltest.add(_ClassPragma("uncollapse_hierarchy"))
qltest.add(_ParametrizedClassPragma("test_with", inherited=True, factory=_schema.get_type_name))
qltest.add(_Parametrized(_ClassPragma("test_with", inherited=True), factory=_schema.get_type_name))
ql.add(_ParametrizedClassPragma("default_doc_name", factory=lambda doc: doc))
ql.add(_Parametrized(_ClassPragma("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))
ql.add(_Parametrized(_Pragma("name"), factory=lambda name: name))
ql.add(_Parametrized(_PropertyPragma("db_table_name"), factory=lambda name: name))
cpp.add(_Pragma("skip"))
rust.add(_Pragma("detach"))
rust.add(_PropertyPragma("detach"))
rust.add(_Pragma("skip_doc_test"))
rust.add(_ParametrizedClassPragma("doc_test_signature", factory=lambda signature: signature))
rust.add(_Parametrized(_ClassPragma("doc_test_signature"), factory=lambda signature: signature))
group = _ParametrizedClassPragma("group", inherited=True, factory=lambda group: group)
group = _Parametrized(_ClassPragma("group", inherited=True), factory=lambda group: group)
synth.add(_ParametrizedClassPragma("from_class", factory=lambda ref: _schema.SynthInfo(
synth.add(_Parametrized(_ClassPragma("from_class"), factory=lambda ref: _schema.SynthInfo(
from_class=_schema.get_type_name(ref))), key="synth")
synth.add(_ParametrizedClassPragma("on_arguments", factory=lambda **kwargs:
synth.add(_Parametrized(_ClassPragma("on_arguments"), factory=lambda **kwargs:
_schema.SynthInfo(on_arguments={k: _schema.get_type_name(t) for k, t in kwargs.items()})), key="synth")

View File

@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.11
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --output-file=misc/codegen/requirements_lock.txt misc/codegen/requirements_in.txt
@@ -8,15 +8,15 @@ inflection==0.5.1
# via -r misc/codegen/requirements_in.txt
iniconfig==2.0.0
# via pytest
packaging==23.2
packaging==24.2
# via pytest
pluggy==1.4.0
pluggy==1.5.0
# via pytest
pystache==0.6.5
pystache==0.6.8
# via -r misc/codegen/requirements_in.txt
pytest==8.0.0
pytest==8.3.5
# via -r misc/codegen/requirements_in.txt
pyyaml==6.0.1
pyyaml==6.0.2
# via -r misc/codegen/requirements_in.txt
toposort==1.10
# via -r misc/codegen/requirements_in.txt

View File

@@ -225,5 +225,25 @@ def test_synth_properties_ignored(generate):
]
def test_properties_with_custom_db_table_names(generate):
assert generate([
schema.Class("Obj", properties=[
schema.OptionalProperty("x", "a", pragmas={"ql_db_table_name": "foo"}),
schema.RepeatedProperty("y", "b", pragmas={"ql_db_table_name": "bar"}),
schema.RepeatedOptionalProperty("z", "c", pragmas={"ql_db_table_name": "baz"}),
schema.PredicateProperty("p", pragmas={"ql_db_table_name": "hello"}),
schema.RepeatedUnorderedProperty("q", "d", pragmas={"ql_db_table_name": "world"}),
]),
]) == [
cpp.Class(name="Obj", final=True, trap_name="Objs", fields=[
cpp.Field("x", "a", is_optional=True, trap_name="Foo"),
cpp.Field("y", "b", is_repeated=True, trap_name="Bar"),
cpp.Field("z", "c", is_repeated=True, is_optional=True, trap_name="Baz"),
cpp.Field("p", "bool", is_predicate=True, trap_name="Hello"),
cpp.Field("q", "d", is_repeated=True, is_unordered=True, trap_name="World"),
]),
]
if __name__ == '__main__':
sys.exit(pytest.main([__file__] + sys.argv[1:]))

View File

@@ -593,5 +593,78 @@ def test_synth_properties_ignored(generate):
)
def test_table_conflict(generate):
with pytest.raises(dbschemegen.Error):
generate([
schema.Class("Foo", properties=[
schema.OptionalProperty("bar", "FooBar"),
]),
schema.Class("FooBar"),
])
def test_table_name_overrides(generate):
assert generate([
schema.Class("Obj", properties=[
schema.OptionalProperty("x", "a", pragmas={"ql_db_table_name": "foo"}),
schema.RepeatedProperty("y", "b", pragmas={"ql_db_table_name": "bar"}),
schema.RepeatedOptionalProperty("z", "c", pragmas={"ql_db_table_name": "baz"}),
schema.PredicateProperty("p", pragmas={"ql_db_table_name": "hello"}),
schema.RepeatedUnorderedProperty("q", "d", pragmas={"ql_db_table_name": "world"}),
]),
]) == dbscheme.Scheme(
src=schema_file.name,
includes=[],
declarations=[
dbscheme.Table(
name="objs",
columns=[
dbscheme.Column("id", "@obj", binding=True),
],
),
dbscheme.Table(
name="foo",
keyset=dbscheme.KeySet(["id"]),
columns=[
dbscheme.Column("id", "@obj"),
dbscheme.Column("x", "a"),
],
),
dbscheme.Table(
name="bar",
keyset=dbscheme.KeySet(["id", "index"]),
columns=[
dbscheme.Column("id", "@obj"),
dbscheme.Column("index", "int"),
dbscheme.Column("y", "b"),
],
),
dbscheme.Table(
name="baz",
keyset=dbscheme.KeySet(["id", "index"]),
columns=[
dbscheme.Column("id", "@obj"),
dbscheme.Column("index", "int"),
dbscheme.Column("z", "c"),
],
),
dbscheme.Table(
name="hello",
keyset=dbscheme.KeySet(["id"]),
columns=[
dbscheme.Column("id", "@obj"),
],
),
dbscheme.Table(
name="world",
columns=[
dbscheme.Column("id", "@obj"),
dbscheme.Column("q", "d"),
],
),
],
)
if __name__ == '__main__':
sys.exit(pytest.main([__file__] + sys.argv[1:]))

View File

@@ -1013,5 +1013,38 @@ def test_hideable_property(generate_classes):
}
def test_property_with_custom_db_table_name(generate_classes):
assert generate_classes([
schema.Class("Obj", properties=[
schema.OptionalProperty("x", "a", pragmas={"ql_db_table_name": "foo"}),
schema.RepeatedProperty("y", "b", pragmas={"ql_db_table_name": "bar"}),
schema.RepeatedOptionalProperty("z", "c", pragmas={"ql_db_table_name": "baz"}),
schema.PredicateProperty("p", pragmas={"ql_db_table_name": "hello"}),
schema.RepeatedUnorderedProperty("q", "d", pragmas={"ql_db_table_name": "world"}),
]),
]) == {
"Obj.qll": (a_ql_class_public(name="Obj"),
a_ql_stub(name="Obj"),
a_ql_class(name="Obj", final=True, properties=[
ql.Property(singular="X", type="a", tablename="foo",
tableparams=["this", "result"],
is_optional=True, doc="x of this obj"),
ql.Property(singular="Y", plural="Ys", type="b", tablename="bar",
tableparams=["this", "index", "result"],
doc="y of this obj", doc_plural="ys of this obj"),
ql.Property(singular="Z", plural="Zs", type="c", tablename="baz",
tableparams=["this", "index", "result"],
is_optional=True, doc="z of this obj", doc_plural="zs of this obj"),
ql.Property(singular="p", type="predicate", tablename="hello",
tableparams=["this"], is_predicate=True,
doc="this obj p"),
ql.Property(singular="Q", plural="Qs", type="d", tablename="world",
tableparams=["this", "result"], is_unordered=True,
doc="q of this obj", doc_plural="qs of this obj"),
],
imports=[stub_import_prefix + "Obj"])),
}
if __name__ == '__main__':
sys.exit(pytest.main([__file__] + sys.argv[1:]))

View File

@@ -272,10 +272,10 @@ def test_builtin_predicate_and_set_children_not_allowed(spec):
_class_pragmas = [
(defs.qltest.collapse_hierarchy, "qltest_collapse_hierarchy"),
(defs.qltest.uncollapse_hierarchy, "qltest_uncollapse_hierarchy"),
(defs.qltest.skip, "qltest_skip"),
]
_property_pragmas = [
(defs.qltest.skip, "qltest_skip"),
(defs.cpp.skip, "cpp_skip"),
(defs.ql.internal, "ql_internal"),
]
@@ -646,6 +646,17 @@ def test_class_default_doc_name():
}
def test_db_table_name():
@load
class data:
class A:
x: optional[int] | defs.ql.db_table_name("foo")
assert data.classes == {
'A': schema.Class('A', properties=[schema.OptionalProperty("x", "int", pragmas={"ql_db_table_name": "foo"})]),
}
def test_null_class():
@load
class data:
@@ -838,7 +849,7 @@ def test_annotate_fields_negations():
@load
class data:
class Root:
x: defs.int | defs.ql.internal | defs.qltest.skip
x: defs.int | defs.ql.internal
y: defs.optional["Root"] | defs.child | defs.desc("foo\nbar\n")
z: defs.string | defs.synth | defs.doc("foo")
@@ -850,7 +861,7 @@ def test_annotate_fields_negations():
assert data.classes == {
"Root": schema.Class("Root", properties=[
schema.SingleProperty("x", "int", pragmas=["qltest_skip"]),
schema.SingleProperty("x", "int"),
schema.OptionalProperty("y", "Root"),
schema.SingleProperty("z", "string"),
]),

View File

@@ -36,7 +36,6 @@ fn property_name(type_name: &str, field_name: &str) -> String {
("CallExpr", "expr") => "function",
("LetExpr", "expr") => "scrutinee",
("MatchExpr", "expr") => "scrutinee",
("Path", "segment") => "part",
(_, "then_branch") => "then",
(_, "else_branch") => "else_",
("ArrayType", "ty") => "element_type_repr",

View File

@@ -1004,7 +1004,7 @@ fn make_qualified_path(
id: trap::TrapId::Star,
text: Some(name),
}));
let part = Some(trap.emit(generated::PathSegment {
let segment = Some(trap.emit(generated::PathSegment {
id: trap::TrapId::Star,
generic_arg_list: None,
name_ref,
@@ -1015,7 +1015,7 @@ fn make_qualified_path(
trap.emit(generated::Path {
id: trap::TrapId::Star,
qualifier,
part,
segment,
})
}
path.into_iter()

View File

@@ -1,2 +1,2 @@
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
top.rs fcff2f1d468e6bc5384e5c0d7f3249773fa3ef38db054c0ec555c43d143117da fcff2f1d468e6bc5384e5c0d7f3249773fa3ef38db054c0ec555c43d143117da
top.rs 49e4f3abb137d6eed5a7c5202b3a31c9cafa1f565ee63dd5960e971950fafaa1 49e4f3abb137d6eed5a7c5202b3a31c9cafa1f565ee63dd5960e971950fafaa1

View File

@@ -2027,7 +2027,7 @@ impl From<trap::Label<Pat>> for trap::Label<Element> {
pub struct Path {
pub id: trap::TrapId<Path>,
pub qualifier: Option<trap::Label<Path>>,
pub part: Option<trap::Label<PathSegment>>,
pub segment: Option<trap::Label<PathSegment>>,
}
impl trap::TrapEntry for Path {
@@ -2040,8 +2040,8 @@ impl trap::TrapEntry for Path {
if let Some(v) = self.qualifier {
out.add_tuple("path_qualifiers", vec![id.into(), v.into()]);
}
if let Some(v) = self.part {
out.add_tuple("path_parts", vec![id.into(), v.into()]);
if let Some(v) = self.segment {
out.add_tuple("path_segments_", vec![id.into(), v.into()]);
}
}
}

View File

@@ -1659,11 +1659,11 @@ impl Translator<'_> {
pub(crate) fn emit_path(&mut self, node: ast::Path) -> Option<Label<generated::Path>> {
let qualifier = node.qualifier().and_then(|x| self.emit_path(x));
let part = node.segment().and_then(|x| self.emit_path_segment(x));
let segment = node.segment().and_then(|x| self.emit_path_segment(x));
let label = self.trap.emit(generated::Path {
id: TrapId::Star,
qualifier,
part,
segment,
});
self.emit_location(label, &node);
emit_detached!(Path, self, node, label);

View File

@@ -579,10 +579,10 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b
lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60
lib/codeql/rust/elements/internal/generated/ParenPat.qll 4f168ef5d5bb87a903251cc31b2e44a759b099ec69c90af31783fbb15778c940 0e34f94a45a13396fd57d94c245dc64d1adde2ab0e22b56946f7e94c04e297fc
lib/codeql/rust/elements/internal/generated/ParenTypeRepr.qll 40ab5c592e7699c621787793743e33988de71ff42ca27599f5ab3ddb70e3f7d8 12c0a6eed2202ee3e892f61da3b3ce77ac3190854cdf3097e8d2be98aa3cb91d
lib/codeql/rust/elements/internal/generated/ParentChild.qll 052cfc8ff7ecdcc941006d07c0381c5255174cf104d15621308e143e4d5401f6 51ffa60668c98ff888b84a06f73b6540d487105ba888de1afd70067df4416509
lib/codeql/rust/elements/internal/generated/ParentChild.qll d5cda732625e48dabe494d264d2b26df2d2e043ca0503052b551ee2cb1518ab7 9ff0d4634f7be4afada224f9eb3607041ea3461b389401a9f2998099037edffe
lib/codeql/rust/elements/internal/generated/ParenthesizedArgList.qll c5fa328ea60d3a3333d7c7bb3480969c1873166c7ac8ebb9d0afad7a8099d1a8 2dbbb6200d96f7db7dea4a55bdeab8d67b14d39a43e0bd54ada019f7e466f163
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
lib/codeql/rust/elements/internal/generated/Path.qll 8e47e91aff3f8c60f1ee8cb3887b8e4936c38e4665d052f2c92a939a969aac29 2c28beb89cabd7c7c91a5bc65c874f414cb96bbefde37b25811b61089a8a0053
lib/codeql/rust/elements/internal/generated/Path.qll 9b12afb46fc5a9ad3a811b05472621bbecccb900c47504feb7f29d96b28421ca bcacbffc36fb3e0c9b26523b5963af0ffa9fd6b19f00a2a31bdb2316071546bd
lib/codeql/rust/elements/internal/generated/PathAstNode.qll e6d4d5bffd3c623baaaee46bc183eb31ce88795535f164f6a9b9b4d98bbd6101 168db515404933479ba6b150c72e012d28592cbc32366aefcb1bf9599dbcd183
lib/codeql/rust/elements/internal/generated/PathExpr.qll 34ebad4d062ce8b7e517f2ab09d52745fb8455203f4a936df7284ad296638387 ba66781cdbdeb89c27a4bfb2be0f27f85fb34978d699b4e343446fb0d7ad2aa6
lib/codeql/rust/elements/internal/generated/PathExprBase.qll d8218e201b8557fa6d9ca2c30b764e5ad9a04a2e4fb695cc7219bbd7636a6ac2 4ef178426d7095a156f4f8c459b4d16f63abc64336cb50a6cf883a5f7ee09113
@@ -594,7 +594,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 51d1e9e683fc79dddbff
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9
lib/codeql/rust/elements/internal/generated/Raw.qll ba65a01002b1eb2dd26a637c5475c06e91f11f1093d820787e5df4226aaa137f 0d8cabba6fa915461b3cce7e065f4f77339798f008c3fc3ab143667321729e67
lib/codeql/rust/elements/internal/generated/Raw.qll 48bb632ea749504184ba9ed85f364806657a6de953eff9492d5c1c509c75b9b0 b5f8a05c79cbb36f95d830994946e58862583f3e16df80c947e8318aa8f17beb
lib/codeql/rust/elements/internal/generated/RecordFieldList.qll 4a23b0d75a90671197246dbbb4e62706c180074abb8ebe60a96df11c47a917a2 09be127977651a24010b090d9681714d83ebd461098f9cf0e0d1973cafb1c782
lib/codeql/rust/elements/internal/generated/RefExpr.qll 7d995884e3dc1c25fc719f5d7253179344d63650e217e9ff6530285fe7a57f64 f2c3c12551deea4964b66553fb9b6423ee16fec53bd63db4796191aa60dc6c66
lib/codeql/rust/elements/internal/generated/RefPat.qll 456ede39837463ee22a630ec7ab6c8630d3664a8ea206fcc6e4f199e92fa564c 5622062765f32930465ba6b170e986706f159f6070f48adee3c20e24e8df4e05
@@ -986,7 +986,7 @@ test/extractor-tests/generated/ParenPat/ParenPat_getPat.ql 96f3db0ec4e71fd870619
test/extractor-tests/generated/ParenTypeRepr/ParenTypeRepr.ql a96bb8b51d8c0c466afc1c076834fa16edf7e67fffe2f641799850dee43099a2 0e6c375e621b7a7756d39e8edd78b671e53d1aac757ac54a26747fe5259c5394
test/extractor-tests/generated/ParenTypeRepr/ParenTypeRepr_getTypeRepr.ql 64fe4ea708bc489ba64ed845f63cfbcd57c1179c57d95be309db37eac2f5eb71 0f4cbbfdf39d89830b5249cabf26d834fc2310b8a9579c19383c90cb4333afb7
test/extractor-tests/generated/ParenthesizedArgList/MISSING_SOURCE.txt b6cf5771fdbbe981aeb3f443ec7a40517b6e99ffc9817fd8872c2e344240dae1 b6cf5771fdbbe981aeb3f443ec7a40517b6e99ffc9817fd8872c2e344240dae1
test/extractor-tests/generated/Path/Path.ql 2bdcd99b3b5ffc83ac47d8cc27a4561d616bcf06844f0c452c699cd10ee640ca 5a7d7ffb8b0c04d6a8cbb2a953761df8561b796c4372bef1bd55c359b2f19911
test/extractor-tests/generated/Path/Path.ql 2b02325ab1739bf41bc5f50d56b1e9cc72fca4093b03f2bda193699121e64448 c4d44402696ce10175ad8286dbd78277fbb81e7e1b886c0c27d5b88a7509052e
test/extractor-tests/generated/Path/PathExpr.ql 5039fe730998a561f51813a0716e18c7c1d36b6da89936e4cfbdb4ef0e895560 cd3ddf8ab93cd573381807f59cded7fb3206f1dbdff582490be6f23bed2d6f29
test/extractor-tests/generated/Path/PathExpr_getAttr.ql 2ccac48cd91d86670c1d2742de20344135d424e6f0e3dafcc059555046f92d92 9b7b5f5f9e3674fad9b3a5bcd3cabc0dff32a95640da0fce6f4d0eb931f1757d
test/extractor-tests/generated/Path/PathExpr_getPath.ql e7894071313a74166bdd31d7cd974037fcd5a7f0e92d5eec42833266196eb858 46a06e8a1207e7a0fa175cd4b61068e5fd6c43b5575b88986409f0ac2be64c51
@@ -1006,8 +1006,8 @@ test/extractor-tests/generated/Path/PathSegment_getTraitTypeRepr.ql d7ea6ee3f6b7
test/extractor-tests/generated/Path/PathSegment_getTypeRepr.ql d9d8ff43a55671616bd5b98ff2c03690ec2661817d19a61edcc4b37d23e312d0 b4dc0ae4d7f03c98c23312b358d214565b34c7a028ba8983826c6bf5c1177eeb
test/extractor-tests/generated/Path/PathTypeRepr.ql c2e069acc5111088a7287d98b4bd4bf44bd79c5a786b275f7448ebafc3613500 6e016750e5fef92a98bc5cc60bfd40d85fbb5eb2d251b4d69ffe600813f81df0
test/extractor-tests/generated/Path/PathTypeRepr_getPath.ql 49e96ea2aa482e3b80cb0e2d944055f8298f7fc55b36cea7468586c94bacf686 29b3c2140ac1bc6e0e6160140e292e2b84e13145c1553480e2a582cd7f7bd3fd
test/extractor-tests/generated/Path/Path_getPart.ql 8aa45a0b58203ef1177166efbe1c2851faf4b4c9a453c83137f0c9298badcdbf b82d490d9b3a8237487cd5da8b3b6fc4aa477977b332a5c6539b3cd4e6d5b45b
test/extractor-tests/generated/Path/Path_getQualifier.ql 9af95e22cdf3a65da6a41d93136aef4523db5ce81d38f6ed4bc613f1c68784d0 3102d9241a417a92c97a53ac56a7a8683463f1adc7a593cda1382c0d25b3f261
test/extractor-tests/generated/Path/Path_getSegment.ql 475f344ee24a14468745d50922fdfd63f5d817f14cc041a184c2f8ec144a01dd 4f663c5c2b1e0cb8b9a8a0b2d8b5d81f12a3bf333c71ecbb43d9258f7dfe4ec7
test/extractor-tests/generated/PrefixExpr/PrefixExpr.ql 44fb7174365c6deecdc22c720d84617c6e060c05d49c41c90433451588f8aa6f 871fab471c82fede3c36edc003f9decee5bb7844c016951d28be78d0c91487e5
test/extractor-tests/generated/PrefixExpr/PrefixExpr_getAttr.ql fdad6ad5199435ded1e4a9ea6b246e76b904cd73a36aaa4780e84eef91741c5b 75d63940046e62c1efa1151b0cac45b5ec0bab5e39aec2e11d43f6c385e37984
test/extractor-tests/generated/PrefixExpr/PrefixExpr_getExpr.ql 2d1d97f6277794871fbb032ea87ac30b1aa902a74cd874720156162057ea202e b1b9880fce07d66df7ec87f12189c37adf9f233a1d0b38a1b09808d052a95642

2
rust/ql/.gitattributes generated vendored
View File

@@ -1008,8 +1008,8 @@
/test/extractor-tests/generated/Path/PathSegment_getTypeRepr.ql linguist-generated
/test/extractor-tests/generated/Path/PathTypeRepr.ql linguist-generated
/test/extractor-tests/generated/Path/PathTypeRepr_getPath.ql linguist-generated
/test/extractor-tests/generated/Path/Path_getPart.ql linguist-generated
/test/extractor-tests/generated/Path/Path_getQualifier.ql linguist-generated
/test/extractor-tests/generated/Path/Path_getSegment.ql linguist-generated
/test/extractor-tests/generated/PrefixExpr/PrefixExpr.ql linguist-generated
/test/extractor-tests/generated/PrefixExpr/PrefixExpr_getAttr.ql linguist-generated
/test/extractor-tests/generated/PrefixExpr/PrefixExpr_getExpr.ql linguist-generated

View File

@@ -32,14 +32,14 @@ module Impl {
result = "...::"
or
index = 1 and
result = this.getPart().toAbbreviatedString()
result = this.getSegment().toAbbreviatedString()
}
/**
* Gets the text of this path, if it exists.
*/
pragma[nomagic]
string getText() { result = this.getPart().getNameRef().getText() }
string getText() { result = this.getSegment().getNameRef().getText() }
}
/** A simple identifier path. */
@@ -49,7 +49,7 @@ module Impl {
IdentPath() {
not this.hasQualifier() and
exists(PathSegment ps |
ps = this.getPart() and
ps = this.getSegment() and
not ps.hasGenericArgList() and
not ps.hasParenthesizedArgList() and
not ps.hasTypeRepr() and

View File

@@ -809,12 +809,12 @@ private module Impl {
}
private Element getImmediateChildOfPath(Path e, int index, string partialPredicateCall) {
exists(int b, int bAstNode, int n, int nQualifier, int nPart |
exists(int b, int bAstNode, int n, int nQualifier, int nSegment |
b = 0 and
bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and
n = bAstNode and
nQualifier = n + 1 and
nPart = nQualifier + 1 and
nSegment = nQualifier + 1 and
(
none()
or
@@ -822,7 +822,7 @@ private module Impl {
or
index = n and result = e.getQualifier() and partialPredicateCall = "Qualifier()"
or
index = nQualifier and result = e.getPart() and partialPredicateCall = "Part()"
index = nQualifier and result = e.getSegment() and partialPredicateCall = "Segment()"
)
)
}

View File

@@ -42,15 +42,16 @@ module Generated {
final predicate hasQualifier() { exists(this.getQualifier()) }
/**
* Gets the part of this path, if it exists.
* Gets the last segment of this path, if it exists.
*/
PathSegment getPart() {
result = Synth::convertPathSegmentFromRaw(Synth::convertPathToRaw(this).(Raw::Path).getPart())
PathSegment getSegment() {
result =
Synth::convertPathSegmentFromRaw(Synth::convertPathToRaw(this).(Raw::Path).getSegment())
}
/**
* Holds if `getPart()` exists.
* Holds if `getSegment()` exists.
*/
final predicate hasPart() { exists(this.getPart()) }
final predicate hasSegment() { exists(this.getSegment()) }
}
}

View File

@@ -721,9 +721,9 @@ module Raw {
Path getQualifier() { path_qualifiers(this, result) }
/**
* Gets the part of this path, if it exists.
* Gets the last segment of this path, if it exists.
*/
PathSegment getPart() { path_parts(this, result) }
PathSegment getSegment() { path_segments_(this, result) }
}
/**

View File

@@ -31,14 +31,14 @@ class StreamCipherInit extends Cryptography::CryptographicOperation::Range {
rawAlgorithmName =
p.getPath()
.getQualifier()
.getPart()
.getSegment()
.getGenericArgList()
.getGenericArg(0)
.(TypeArg)
.getTypeRepr()
.(PathTypeRepr)
.getPath()
.getPart()
.getSegment()
.getNameRef()
.getText()
) and

View File

@@ -378,7 +378,7 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
pragma[nomagic]
private TypeRepr getASelfTyArg() {
result =
this.getSelfPath().getPart().getGenericArgList().getAGenericArg().(TypeArg).getTypeRepr()
this.getSelfPath().getSegment().getGenericArgList().getAGenericArg().(TypeArg).getTypeRepr()
}
/**

View File

@@ -240,7 +240,7 @@ private Type inferImplicitSelfType(SelfParam self, TypePath path) {
*/
private TypeMention getExplicitTypeArgMention(Path path, TypeParam tp) {
exists(int i |
result = path.getPart().getGenericArgList().getTypeArg(pragma[only_bind_into](i)) and
result = path.getSegment().getGenericArgList().getTypeArg(pragma[only_bind_into](i)) and
tp = resolvePath(path).getTypeParam(pragma[only_bind_into](i))
)
or

View File

@@ -78,7 +78,7 @@ class TypeReprMention extends TypeMention, TypeRepr {
class PathMention extends TypeMention, Path {
override TypeMention getTypeArgument(int i) {
result = this.getPart().getGenericArgList().getTypeArg(i)
result = this.getSegment().getGenericArgList().getTypeArg(i)
or
// `Self` paths inside traits and `impl` blocks have implicit type arguments
// that are the type parameters of the trait or impl. For example, in
@@ -93,7 +93,7 @@ class PathMention extends TypeMention, Path {
//
// the `Self` return type is shorthand for `Foo<T>`.
exists(ImplOrTraitItemNode node | this = node.getASelfPath() |
result = node.(ImplItemNode).getSelfPath().getPart().getGenericArgList().getTypeArg(i)
result = node.(ImplItemNode).getSelfPath().getSegment().getGenericArgList().getTypeArg(i)
or
result = node.(Trait).getGenericParamList().getTypeParam(i)
)
@@ -140,7 +140,7 @@ private predicate isImplSelfTypeParam(
) {
exists(PathMention path |
selfPath = impl.getSelfPath() and
path = selfPath.getPart().getGenericArgList().getTypeArg(i).(PathTypeRepr).getPath() and
path = selfPath.getSegment().getGenericArgList().getTypeArg(i).(PathTypeRepr).getPath() and
tp = path.resolveType()
)
}

View File

@@ -63,7 +63,7 @@ private class RegexInjectionDefaultBarrier extends RegexInjectionBarrier {
.getFunction()
.(PathExpr)
.getPath()
.getPart()
.getSegment()
.getNameRef()
.getText() = "escape"
}

View File

@@ -772,9 +772,9 @@ path_qualifiers(
);
#keyset[id]
path_parts(
path_segments_(
int id: @path ref,
int part: @path_segment ref
int segment: @path_segment ref
);
path_segments(

View File

@@ -1,25 +1,25 @@
| gen_path.rs:5:9:5:18 | some_crate | hasQualifier: | no | hasPart: | yes |
| gen_path.rs:5:9:5:31 | ...::some_module | hasQualifier: | yes | hasPart: | yes |
| gen_path.rs:5:9:5:42 | ...::some_item | hasQualifier: | yes | hasPart: | yes |
| gen_path.rs:6:5:6:7 | foo | hasQualifier: | no | hasPart: | yes |
| gen_path.rs:6:5:6:12 | ...::bar | hasQualifier: | yes | hasPart: | yes |
| gen_path_expr.rs:5:13:5:20 | variable | hasQualifier: | no | hasPart: | yes |
| gen_path_expr.rs:6:13:6:15 | foo | hasQualifier: | no | hasPart: | yes |
| gen_path_expr.rs:6:13:6:20 | ...::bar | hasQualifier: | yes | hasPart: | yes |
| gen_path_expr.rs:7:13:7:15 | <...> | hasQualifier: | no | hasPart: | yes |
| gen_path_expr.rs:7:13:7:20 | ...::foo | hasQualifier: | yes | hasPart: | yes |
| gen_path_expr.rs:7:14:7:14 | T | hasQualifier: | no | hasPart: | yes |
| gen_path_expr.rs:8:13:8:31 | <...> | hasQualifier: | no | hasPart: | yes |
| gen_path_expr.rs:8:13:8:36 | ...::foo | hasQualifier: | yes | hasPart: | yes |
| gen_path_expr.rs:8:14:8:21 | TypeRepr | hasQualifier: | no | hasPart: | yes |
| gen_path_expr.rs:8:26:8:30 | Trait | hasQualifier: | no | hasPart: | yes |
| gen_path_pat.rs:5:11:5:11 | x | hasQualifier: | no | hasPart: | yes |
| gen_path_pat.rs:6:9:6:11 | Foo | hasQualifier: | no | hasPart: | yes |
| gen_path_pat.rs:6:9:6:16 | ...::Bar | hasQualifier: | yes | hasPart: | yes |
| gen_path_type_repr.rs:5:14:5:16 | std | hasQualifier: | no | hasPart: | yes |
| gen_path_type_repr.rs:5:14:5:29 | ...::collections | hasQualifier: | yes | hasPart: | yes |
| gen_path_type_repr.rs:5:14:5:48 | ...::HashMap::<...> | hasQualifier: | yes | hasPart: | yes |
| gen_path_type_repr.rs:5:40:5:42 | i32 | hasQualifier: | no | hasPart: | yes |
| gen_path_type_repr.rs:5:45:5:47 | i32 | hasQualifier: | no | hasPart: | yes |
| gen_path_type_repr.rs:6:14:6:14 | X | hasQualifier: | no | hasPart: | yes |
| gen_path_type_repr.rs:6:14:6:20 | ...::Item | hasQualifier: | yes | hasPart: | yes |
| gen_path.rs:5:9:5:18 | some_crate | hasQualifier: | no | hasSegment: | yes |
| gen_path.rs:5:9:5:31 | ...::some_module | hasQualifier: | yes | hasSegment: | yes |
| gen_path.rs:5:9:5:42 | ...::some_item | hasQualifier: | yes | hasSegment: | yes |
| gen_path.rs:6:5:6:7 | foo | hasQualifier: | no | hasSegment: | yes |
| gen_path.rs:6:5:6:12 | ...::bar | hasQualifier: | yes | hasSegment: | yes |
| gen_path_expr.rs:5:13:5:20 | variable | hasQualifier: | no | hasSegment: | yes |
| gen_path_expr.rs:6:13:6:15 | foo | hasQualifier: | no | hasSegment: | yes |
| gen_path_expr.rs:6:13:6:20 | ...::bar | hasQualifier: | yes | hasSegment: | yes |
| gen_path_expr.rs:7:13:7:15 | <...> | hasQualifier: | no | hasSegment: | yes |
| gen_path_expr.rs:7:13:7:20 | ...::foo | hasQualifier: | yes | hasSegment: | yes |
| gen_path_expr.rs:7:14:7:14 | T | hasQualifier: | no | hasSegment: | yes |
| gen_path_expr.rs:8:13:8:31 | <...> | hasQualifier: | no | hasSegment: | yes |
| gen_path_expr.rs:8:13:8:36 | ...::foo | hasQualifier: | yes | hasSegment: | yes |
| gen_path_expr.rs:8:14:8:21 | TypeRepr | hasQualifier: | no | hasSegment: | yes |
| gen_path_expr.rs:8:26:8:30 | Trait | hasQualifier: | no | hasSegment: | yes |
| gen_path_pat.rs:5:11:5:11 | x | hasQualifier: | no | hasSegment: | yes |
| gen_path_pat.rs:6:9:6:11 | Foo | hasQualifier: | no | hasSegment: | yes |
| gen_path_pat.rs:6:9:6:16 | ...::Bar | hasQualifier: | yes | hasSegment: | yes |
| gen_path_type_repr.rs:5:14:5:16 | std | hasQualifier: | no | hasSegment: | yes |
| gen_path_type_repr.rs:5:14:5:29 | ...::collections | hasQualifier: | yes | hasSegment: | yes |
| gen_path_type_repr.rs:5:14:5:48 | ...::HashMap::<...> | hasQualifier: | yes | hasSegment: | yes |
| gen_path_type_repr.rs:5:40:5:42 | i32 | hasQualifier: | no | hasSegment: | yes |
| gen_path_type_repr.rs:5:45:5:47 | i32 | hasQualifier: | no | hasSegment: | yes |
| gen_path_type_repr.rs:6:14:6:14 | X | hasQualifier: | no | hasSegment: | yes |
| gen_path_type_repr.rs:6:14:6:20 | ...::Item | hasQualifier: | yes | hasSegment: | yes |

View File

@@ -2,10 +2,10 @@
import codeql.rust.elements
import TestUtils
from Path x, string hasQualifier, string hasPart
from Path x, string hasQualifier, string hasSegment
where
toBeTested(x) and
not x.isUnknown() and
(if x.hasQualifier() then hasQualifier = "yes" else hasQualifier = "no") and
if x.hasPart() then hasPart = "yes" else hasPart = "no"
select x, "hasQualifier:", hasQualifier, "hasPart:", hasPart
if x.hasSegment() then hasSegment = "yes" else hasSegment = "no"
select x, "hasQualifier:", hasQualifier, "hasSegment:", hasSegment

View File

@@ -0,0 +1,25 @@
| gen_path.rs:5:9:5:18 | some_crate | gen_path.rs:5:9:5:18 | some_crate |
| gen_path.rs:5:9:5:31 | ...::some_module | gen_path.rs:5:21:5:31 | some_module |
| gen_path.rs:5:9:5:42 | ...::some_item | gen_path.rs:5:34:5:42 | some_item |
| gen_path.rs:6:5:6:7 | foo | gen_path.rs:6:5:6:7 | foo |
| gen_path.rs:6:5:6:12 | ...::bar | gen_path.rs:6:10:6:12 | bar |
| gen_path_expr.rs:5:13:5:20 | variable | gen_path_expr.rs:5:13:5:20 | variable |
| gen_path_expr.rs:6:13:6:15 | foo | gen_path_expr.rs:6:13:6:15 | foo |
| gen_path_expr.rs:6:13:6:20 | ...::bar | gen_path_expr.rs:6:18:6:20 | bar |
| gen_path_expr.rs:7:13:7:15 | <...> | gen_path_expr.rs:7:13:7:15 | <...> |
| gen_path_expr.rs:7:13:7:20 | ...::foo | gen_path_expr.rs:7:18:7:20 | foo |
| gen_path_expr.rs:7:14:7:14 | T | gen_path_expr.rs:7:14:7:14 | T |
| gen_path_expr.rs:8:13:8:31 | <...> | gen_path_expr.rs:8:13:8:31 | <...> |
| gen_path_expr.rs:8:13:8:36 | ...::foo | gen_path_expr.rs:8:34:8:36 | foo |
| gen_path_expr.rs:8:14:8:21 | TypeRepr | gen_path_expr.rs:8:14:8:21 | TypeRepr |
| gen_path_expr.rs:8:26:8:30 | Trait | gen_path_expr.rs:8:26:8:30 | Trait |
| gen_path_pat.rs:5:11:5:11 | x | gen_path_pat.rs:5:11:5:11 | x |
| gen_path_pat.rs:6:9:6:11 | Foo | gen_path_pat.rs:6:9:6:11 | Foo |
| gen_path_pat.rs:6:9:6:16 | ...::Bar | gen_path_pat.rs:6:14:6:16 | Bar |
| gen_path_type_repr.rs:5:14:5:16 | std | gen_path_type_repr.rs:5:14:5:16 | std |
| gen_path_type_repr.rs:5:14:5:29 | ...::collections | gen_path_type_repr.rs:5:19:5:29 | collections |
| gen_path_type_repr.rs:5:14:5:48 | ...::HashMap::<...> | gen_path_type_repr.rs:5:32:5:48 | HashMap::<...> |
| gen_path_type_repr.rs:5:40:5:42 | i32 | gen_path_type_repr.rs:5:40:5:42 | i32 |
| gen_path_type_repr.rs:5:45:5:47 | i32 | gen_path_type_repr.rs:5:45:5:47 | i32 |
| gen_path_type_repr.rs:6:14:6:14 | X | gen_path_type_repr.rs:6:14:6:14 | X |
| gen_path_type_repr.rs:6:14:6:20 | ...::Item | gen_path_type_repr.rs:6:17:6:20 | Item |

View File

@@ -4,4 +4,4 @@ import TestUtils
from Path x
where toBeTested(x) and not x.isUnknown()
select x, x.getPart()
select x, x.getSegment()

View File

@@ -87,6 +87,7 @@ class _:
foo::bar;
```
"""
segment: _ | ql.db_table_name("path_segments_") | doc("last segment of this path")
@annotate(GenericArgList)

2
rust/schema/ast.py generated
View File

@@ -482,7 +482,7 @@ class ParenthesizedArgList(AstNode, ):
class Path(AstNode, ):
qualifier: optional["Path"] | child
part: optional["PathSegment"] | child
segment: optional["PathSegment"] | child
class PathExpr(Expr, ):
attrs: list["Attr"] | child