Merge pull request #18116 from github/redsun82/rust-perf-measures

Rust: add some performance diagnostics
This commit is contained in:
Paolo Tranquilli
2024-12-04 14:31:06 +01:00
committed by GitHub
66 changed files with 966 additions and 131 deletions

6
Cargo.lock generated
View File

@@ -381,6 +381,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"argfile",
"chrono",
"clap",
"codeql-extractor",
"dunce",
@@ -405,6 +406,7 @@ dependencies = [
"ra_ap_vfs",
"rust-extractor-macros",
"serde",
"serde_json",
"serde_with",
"stderrlog",
"triomphe",
@@ -2041,9 +2043,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.132"
version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
dependencies = [
"itoa",
"memchr",

View File

@@ -68,7 +68,7 @@ use_repo(py_deps, "vendor__anyhow-1.0.44", "vendor__cc-1.0.70", "vendor__clap-2.
# deps for ruby+rust
# keep in sync by running `misc/bazel/3rdparty/update_cargo_deps.sh`
tree_sitter_extractors_deps = use_extension("//misc/bazel/3rdparty:tree_sitter_extractors_extension.bzl", "r")
use_repo(tree_sitter_extractors_deps, "vendor__anyhow-1.0.93", "vendor__argfile-0.2.1", "vendor__chrono-0.4.38", "vendor__clap-4.5.20", "vendor__dunce-1.0.5", "vendor__encoding-0.2.33", "vendor__figment-0.10.19", "vendor__flate2-1.0.34", "vendor__glob-0.3.1", "vendor__globset-0.4.15", "vendor__itertools-0.10.5", "vendor__itertools-0.13.0", "vendor__lazy_static-1.5.0", "vendor__log-0.4.22", "vendor__num-traits-0.2.19", "vendor__num_cpus-1.16.0", "vendor__proc-macro2-1.0.89", "vendor__quote-1.0.37", "vendor__ra_ap_base_db-0.0.232", "vendor__ra_ap_cfg-0.0.232", "vendor__ra_ap_hir-0.0.232", "vendor__ra_ap_hir_def-0.0.232", "vendor__ra_ap_hir_expand-0.0.232", "vendor__ra_ap_ide_db-0.0.232", "vendor__ra_ap_intern-0.0.232", "vendor__ra_ap_load-cargo-0.0.232", "vendor__ra_ap_parser-0.0.232", "vendor__ra_ap_paths-0.0.232", "vendor__ra_ap_project_model-0.0.232", "vendor__ra_ap_span-0.0.232", "vendor__ra_ap_syntax-0.0.232", "vendor__ra_ap_vfs-0.0.232", "vendor__rand-0.8.5", "vendor__rayon-1.10.0", "vendor__regex-1.11.1", "vendor__serde-1.0.214", "vendor__serde_json-1.0.132", "vendor__serde_with-3.11.0", "vendor__stderrlog-0.6.0", "vendor__syn-2.0.87", "vendor__tracing-0.1.40", "vendor__tracing-subscriber-0.3.18", "vendor__tree-sitter-0.24.4", "vendor__tree-sitter-embedded-template-0.23.2", "vendor__tree-sitter-json-0.24.8", "vendor__tree-sitter-ql-0.23.1", "vendor__tree-sitter-ruby-0.23.1", "vendor__triomphe-0.1.14", "vendor__ungrammar-1.16.1")
use_repo(tree_sitter_extractors_deps, "vendor__anyhow-1.0.93", "vendor__argfile-0.2.1", "vendor__chrono-0.4.38", "vendor__clap-4.5.20", "vendor__dunce-1.0.5", "vendor__encoding-0.2.33", "vendor__figment-0.10.19", "vendor__flate2-1.0.34", "vendor__glob-0.3.1", "vendor__globset-0.4.15", "vendor__itertools-0.10.5", "vendor__itertools-0.13.0", "vendor__lazy_static-1.5.0", "vendor__log-0.4.22", "vendor__num-traits-0.2.19", "vendor__num_cpus-1.16.0", "vendor__proc-macro2-1.0.89", "vendor__quote-1.0.37", "vendor__ra_ap_base_db-0.0.232", "vendor__ra_ap_cfg-0.0.232", "vendor__ra_ap_hir-0.0.232", "vendor__ra_ap_hir_def-0.0.232", "vendor__ra_ap_hir_expand-0.0.232", "vendor__ra_ap_ide_db-0.0.232", "vendor__ra_ap_intern-0.0.232", "vendor__ra_ap_load-cargo-0.0.232", "vendor__ra_ap_parser-0.0.232", "vendor__ra_ap_paths-0.0.232", "vendor__ra_ap_project_model-0.0.232", "vendor__ra_ap_span-0.0.232", "vendor__ra_ap_syntax-0.0.232", "vendor__ra_ap_vfs-0.0.232", "vendor__rand-0.8.5", "vendor__rayon-1.10.0", "vendor__regex-1.11.1", "vendor__serde-1.0.214", "vendor__serde_json-1.0.133", "vendor__serde_with-3.11.0", "vendor__stderrlog-0.6.0", "vendor__syn-2.0.87", "vendor__tracing-0.1.40", "vendor__tracing-subscriber-0.3.18", "vendor__tree-sitter-0.24.4", "vendor__tree-sitter-embedded-template-0.23.2", "vendor__tree-sitter-json-0.24.8", "vendor__tree-sitter-ql-0.23.1", "vendor__tree-sitter-ruby-0.23.1", "vendor__triomphe-0.1.14", "vendor__ungrammar-1.16.1")
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
dotnet.toolchain(dotnet_version = "9.0.100")

View File

@@ -249,7 +249,7 @@ alias(
alias(
name = "serde_json",
actual = "@vendor__serde_json-1.0.132//:serde_json",
actual = "@vendor__serde_json-1.0.133//:serde_json",
tags = ["manual"],
)

View File

@@ -86,7 +86,7 @@ rust_library(
"@vendor__cargo-platform-0.1.8//:cargo_platform",
"@vendor__semver-1.0.23//:semver",
"@vendor__serde-1.0.214//:serde",
"@vendor__serde_json-1.0.132//:serde_json",
"@vendor__serde_json-1.0.133//:serde_json",
"@vendor__thiserror-1.0.69//:thiserror",
],
)

View File

@@ -96,7 +96,7 @@ rust_library(
"@vendor__ra_ap_tt-0.0.232//:ra_ap_tt",
"@vendor__rustc-hash-1.1.0//:rustc_hash",
"@vendor__serde-1.0.214//:serde",
"@vendor__serde_json-1.0.132//:serde_json",
"@vendor__serde_json-1.0.133//:serde_json",
"@vendor__tracing-0.1.40//:tracing",
],
)

View File

@@ -102,7 +102,7 @@ rust_library(
"@vendor__rustc-hash-1.1.0//:rustc_hash",
"@vendor__semver-1.0.23//:semver",
"@vendor__serde-1.0.214//:serde",
"@vendor__serde_json-1.0.132//:serde_json",
"@vendor__serde_json-1.0.133//:serde_json",
"@vendor__tracing-0.1.40//:tracing",
"@vendor__triomphe-0.1.14//:triomphe",
],

View File

@@ -83,13 +83,13 @@ rust_library(
"@rules_rust//rust/platform:x86_64-unknown-none": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
version = "1.0.132",
version = "1.0.133",
deps = [
"@vendor__itoa-1.0.11//:itoa",
"@vendor__memchr-2.7.4//:memchr",
"@vendor__ryu-1.0.18//:ryu",
"@vendor__serde-1.0.214//:serde",
"@vendor__serde_json-1.0.132//:build_script_build",
"@vendor__serde_json-1.0.133//:build_script_build",
],
)
@@ -143,7 +143,7 @@ cargo_build_script(
"noclippy",
"norustfmt",
],
version = "1.0.132",
version = "1.0.133",
visibility = ["//visibility:private"],
)

View File

@@ -320,6 +320,7 @@ _NORMAL_DEPENDENCIES = {
_COMMON_CONDITION: {
"anyhow": Label("@vendor__anyhow-1.0.93//:anyhow"),
"argfile": Label("@vendor__argfile-0.2.1//:argfile"),
"chrono": Label("@vendor__chrono-0.4.38//:chrono"),
"clap": Label("@vendor__clap-4.5.20//:clap"),
"dunce": Label("@vendor__dunce-1.0.5//:dunce"),
"figment": Label("@vendor__figment-0.10.19//:figment"),
@@ -342,6 +343,7 @@ _NORMAL_DEPENDENCIES = {
"ra_ap_syntax": Label("@vendor__ra_ap_syntax-0.0.232//:ra_ap_syntax"),
"ra_ap_vfs": Label("@vendor__ra_ap_vfs-0.0.232//:ra_ap_vfs"),
"serde": Label("@vendor__serde-1.0.214//:serde"),
"serde_json": Label("@vendor__serde_json-1.0.133//:serde_json"),
"serde_with": Label("@vendor__serde_with-3.11.0//:serde_with"),
"stderrlog": Label("@vendor__stderrlog-0.6.0//:stderrlog"),
"triomphe": Label("@vendor__triomphe-0.1.14//:triomphe"),
@@ -364,7 +366,7 @@ _NORMAL_DEPENDENCIES = {
"rayon": Label("@vendor__rayon-1.10.0//:rayon"),
"regex": Label("@vendor__regex-1.11.1//:regex"),
"serde": Label("@vendor__serde-1.0.214//:serde"),
"serde_json": Label("@vendor__serde_json-1.0.132//:serde_json"),
"serde_json": Label("@vendor__serde_json-1.0.133//:serde_json"),
"tracing": Label("@vendor__tracing-0.1.40//:tracing"),
"tracing-subscriber": Label("@vendor__tracing-subscriber-0.3.18//:tracing_subscriber"),
"tree-sitter": Label("@vendor__tree-sitter-0.24.4//:tree_sitter"),
@@ -2519,12 +2521,12 @@ def crate_repositories():
maybe(
http_archive,
name = "vendor__serde_json-1.0.132",
sha256 = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03",
name = "vendor__serde_json-1.0.133",
sha256 = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377",
type = "tar.gz",
urls = ["https://static.crates.io/crates/serde_json/1.0.132/download"],
strip_prefix = "serde_json-1.0.132",
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.serde_json-1.0.132.bazel"),
urls = ["https://static.crates.io/crates/serde_json/1.0.133/download"],
strip_prefix = "serde_json-1.0.133",
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.serde_json-1.0.133.bazel"),
)
maybe(
@@ -3353,7 +3355,7 @@ def crate_repositories():
struct(repo = "vendor__rayon-1.10.0", is_dev_dep = False),
struct(repo = "vendor__regex-1.11.1", is_dev_dep = False),
struct(repo = "vendor__serde-1.0.214", is_dev_dep = False),
struct(repo = "vendor__serde_json-1.0.132", is_dev_dep = False),
struct(repo = "vendor__serde_json-1.0.133", is_dev_dep = False),
struct(repo = "vendor__serde_with-3.11.0", is_dev_dep = False),
struct(repo = "vendor__stderrlog-0.6.0", is_dev_dep = False),
struct(repo = "vendor__syn-2.0.87", is_dev_dep = False),

View File

@@ -110,7 +110,8 @@ def cls_to_dbscheme(cls: schema.Class, lookup: typing.Dict[str, schema.Class], a
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() for d in cls_to_dbscheme(cls, data.classes, add_or_none_except)]
declarations = [d for cls in data.classes.values() if not cls.imported for d in cls_to_dbscheme(cls,
data.classes, add_or_none_except)]
if data.null:
property_classes = {
prop.type for cls in data.classes.values() for prop in cls.properties

View File

@@ -105,8 +105,17 @@ def _get_doc(cls: schema.Class, prop: schema.Property, plural=None):
return f"{prop_name} of this {class_name}"
def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dict[str, schema.Class],
def _type_is_hideable(t: str, lookup: typing.Dict[str, schema.ClassBase]) -> bool:
if t in lookup:
match lookup[t]:
case schema.Class() as cls:
return "ql_hideable" in cls.pragmas
return False
def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dict[str, schema.ClassBase],
prev_child: str = "") -> ql.Property:
args = dict(
type=prop.type if not prop.is_predicate else "predicate",
qltest_skip="qltest_skip" in prop.pragmas,
@@ -116,7 +125,8 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
is_unordered=prop.is_unordered,
description=prop.description,
synth=bool(cls.synth) or prop.synth,
type_is_hideable="ql_hideable" in lookup[prop.type].pragmas if prop.type in lookup else False,
type_is_hideable=_type_is_hideable(prop.type, lookup),
type_is_codegen_class=prop.type in lookup and not lookup[prop.type].imported,
internal="ql_internal" in prop.pragmas,
)
ql_name = prop.pragmas.get("ql_name", prop.name)
@@ -155,7 +165,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
return ql.Property(**args)
def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> ql.Class:
def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.ClassBase]) -> ql.Class:
if "ql_name" in cls.pragmas:
raise Error("ql_name is not supported yet for classes, only for properties")
prev_child = ""
@@ -392,14 +402,15 @@ def generate(opts, renderer):
data = schemaloader.load_file(input)
classes = {name: get_ql_class(cls, data.classes) for name, cls in data.classes.items()}
classes = {name: get_ql_class(cls, data.classes) for name, cls in data.classes.items() if not cls.imported}
if not classes:
raise NoClasses
root = next(iter(classes.values()))
if root.has_children:
raise RootElementHasChildren(root)
imports = {}
pre_imports = {n: cls.module for n, cls in data.classes.items() if cls.imported}
imports = dict(pre_imports)
imports_impl = {}
classes_used_by = {}
cfg_classes = []
@@ -411,7 +422,7 @@ def generate(opts, renderer):
force=opts.force) as renderer:
db_classes = [cls for name, cls in classes.items() if not data.classes[name].synth]
renderer.render(ql.DbClasses(db_classes), out / "Raw.qll")
renderer.render(ql.DbClasses(classes=db_classes, imports=sorted(set(pre_imports.values()))), 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:
@@ -440,6 +451,8 @@ def generate(opts, renderer):
renderer.render(cfg_classes_val, cfg_qll)
for c in data.classes.values():
if c.imported:
continue
path = _get_path(c)
path_impl = _get_path_impl(c)
stub_file = stub_out / path_impl
@@ -458,7 +471,7 @@ def generate(opts, renderer):
renderer.render(class_public, class_public_file)
# for example path/to/elements -> path/to/elements.qll
renderer.render(ql.ImportList([i for name, i in imports.items() if not classes[name].internal]),
renderer.render(ql.ImportList([i for name, i in imports.items() if name not in classes or not classes[name].internal]),
include_file)
elements_module = get_import(include_file, opts.root_dir)
@@ -466,12 +479,15 @@ def generate(opts, renderer):
renderer.render(
ql.GetParentImplementation(
classes=list(classes.values()),
imports=[elements_module] + [i for name, i in imports.items() if classes[name].internal],
imports=[elements_module] + [i for name,
i in imports.items() if name in classes and classes[name].internal],
),
out / 'ParentChild.qll')
if test_out:
for c in data.classes.values():
if c.imported:
continue
if should_skip_qltest(c, data.classes):
continue
test_with_name = c.pragmas.get("qltest_test_with")
@@ -501,7 +517,8 @@ def generate(opts, renderer):
constructor_imports = []
synth_constructor_imports = []
stubs = {}
for cls in sorted(data.classes.values(), key=lambda cls: (cls.group, cls.name)):
for cls in sorted((cls for cls in data.classes.values() if not cls.imported),
key=lambda cls: (cls.group, cls.name)):
synth_type = get_ql_synth_class(cls)
if synth_type.is_final:
final_synth_types.append(synth_type)

View File

@@ -49,7 +49,7 @@ def _get_field(cls: schema.Class, p: schema.Property) -> rust.Field:
def _get_properties(
cls: schema.Class, lookup: dict[str, schema.Class],
cls: schema.Class, lookup: dict[str, schema.ClassBase],
) -> typing.Iterable[tuple[schema.Class, schema.Property]]:
for b in cls.bases:
yield from _get_properties(lookup[b], lookup)
@@ -58,12 +58,14 @@ def _get_properties(
def _get_ancestors(
cls: schema.Class, lookup: dict[str, schema.Class]
cls: schema.Class, lookup: dict[str, schema.ClassBase]
) -> typing.Iterable[schema.Class]:
for b in cls.bases:
base = lookup[b]
yield base
yield from _get_ancestors(base, lookup)
if not base.imported:
base = typing.cast(schema.Class, base)
yield base
yield from _get_ancestors(base, lookup)
class Processor:
@@ -71,7 +73,7 @@ class Processor:
self._classmap = data.classes
def _get_class(self, name: str) -> rust.Class:
cls = self._classmap[name]
cls = typing.cast(schema.Class, self._classmap[name])
properties = [
(c, p)
for c, p in _get_properties(cls, self._classmap)
@@ -101,8 +103,10 @@ class Processor:
def get_classes(self):
ret = {"": []}
for k, cls in self._classmap.items():
if not cls.synth:
if not cls.imported and not cls.synth:
ret.setdefault(cls.group, []).append(self._get_class(cls.name))
elif cls.imported:
ret[""].append(rust.Class(name=cls.name))
return ret

View File

@@ -56,6 +56,8 @@ def generate(opts, renderer):
registry=opts.ql_test_output / ".generated_tests.list",
force=opts.force) as renderer:
for cls in schema.classes.values():
if cls.imported:
continue
if (qlgen.should_skip_qltest(cls, schema.classes) or
"rust_skip_doc_test" in cls.pragmas):
continue

View File

@@ -44,6 +44,7 @@ class Property:
doc_plural: Optional[str] = None
synth: bool = False
type_is_hideable: bool = False
type_is_codegen_class: bool = False
internal: bool = False
cfg: bool = False
@@ -66,10 +67,6 @@ class Property:
article = "An" if self.singular[0] in "AEIO" else "A"
return f"get{article}{self.singular}"
@property
def type_is_class(self):
return bool(self.type) and self.type[0].isupper()
@property
def is_repeated(self):
return bool(self.plural)
@@ -191,6 +188,7 @@ class DbClasses:
template: ClassVar = 'ql_db'
classes: List[Class] = field(default_factory=list)
imports: List[str] = field(default_factory=list)
@dataclass

View File

@@ -3,7 +3,7 @@ import abc
import typing
from collections.abc import Iterable
from dataclasses import dataclass, field
from typing import List, Set, Union, Dict, Optional
from typing import List, Set, Union, Dict, Optional, FrozenSet
from enum import Enum, auto
import functools
@@ -87,8 +87,22 @@ class SynthInfo:
@dataclass
class Class:
class ClassBase:
imported: typing.ClassVar[bool]
name: str
@dataclass
class ImportedClass(ClassBase):
imported: typing.ClassVar[bool] = True
module: str
@dataclass
class Class(ClassBase):
imported: typing.ClassVar[bool] = False
bases: List[str] = field(default_factory=list)
derived: Set[str] = field(default_factory=set)
properties: List[Property] = field(default_factory=list)
@@ -133,7 +147,7 @@ class Class:
@dataclass
class Schema:
classes: Dict[str, Class] = field(default_factory=dict)
classes: Dict[str, ClassBase] = field(default_factory=dict)
includes: List[str] = field(default_factory=list)
null: Optional[str] = None
@@ -155,7 +169,7 @@ class Schema:
predicate_marker = object()
TypeRef = Union[type, str]
TypeRef = type | str | ImportedClass
def get_type_name(arg: TypeRef) -> str:
@@ -164,6 +178,8 @@ def get_type_name(arg: TypeRef) -> str:
return arg.__name__
case str():
return arg
case ImportedClass():
return arg.name
case _:
raise Error(f"Not a schema type or string ({arg})")
@@ -172,9 +188,9 @@ def _make_property(arg: object) -> Property:
match arg:
case _ if arg is predicate_marker:
return PredicateProperty()
case str() | type():
case (str() | type() | ImportedClass()) as arg:
return SingleProperty(type=get_type_name(arg))
case Property():
case Property() as arg:
return arg
case _:
raise Error(f"Illegal property specifier {arg}")

View File

@@ -8,8 +8,6 @@ from misc.codegen.lib import schema as _schema
import inspect as _inspect
from dataclasses import dataclass as _dataclass
from misc.codegen.lib.schema import Property
_set = set
@@ -69,6 +67,9 @@ def include(source: str):
_inspect.currentframe().f_back.f_locals.setdefault("includes", []).append(source)
imported = _schema.ImportedClass
@_dataclass
class _Namespace:
""" simple namespacing mechanism """
@@ -264,7 +265,7 @@ class _PropertyModifierList(_schema.PropertyModifier):
def __or__(self, other: _schema.PropertyModifier):
return _PropertyModifierList(self._mods + (other,))
def modify(self, prop: Property):
def modify(self, prop: _schema.Property):
for m in self._mods:
m.modify(prop)

View File

@@ -132,6 +132,7 @@ def _check_test_with(classes: typing.Dict[str, schema.Class]):
def load(m: types.ModuleType) -> schema.Schema:
includes = set()
classes = {}
imported_classes = {}
known = {"int", "string", "boolean"}
known.update(n for n in m.__dict__ if not n.startswith("__"))
import misc.codegen.lib.schemadefs as defs
@@ -146,6 +147,9 @@ def load(m: types.ModuleType) -> schema.Schema:
continue
if isinstance(data, types.ModuleType):
continue
if isinstance(data, schema.ImportedClass):
imported_classes[name] = data
continue
cls = _get_class(data)
if classes and not cls.bases:
raise schema.Error(
@@ -162,7 +166,7 @@ def load(m: types.ModuleType) -> schema.Schema:
_fill_hideable_information(classes)
_check_test_with(classes)
return schema.Schema(includes=includes, classes=_toposort_classes_by_group(classes), null=null)
return schema.Schema(includes=includes, classes=imported_classes | _toposort_classes_by_group(classes), null=null)
def load_file(path: pathlib.Path) -> schema.Schema:

View File

@@ -113,7 +113,7 @@ module Generated {
*/
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
{{^synth}}
{{^is_predicate}}result = {{/is_predicate}}{{#type_is_class}}Synth::convert{{type}}FromRaw({{/type_is_class}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}}){{#type_is_class}}){{/type_is_class}}
{{^is_predicate}}result = {{/is_predicate}}{{#type_is_codegen_class}}Synth::convert{{type}}FromRaw({{/type_is_codegen_class}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}}){{#type_is_codegen_class}}){{/type_is_codegen_class}}
{{/synth}}
{{#synth}}
none()

View File

@@ -3,6 +3,10 @@
* This module holds thin fully generated class definitions around DB entities.
*/
module Raw {
{{#imports}}
private import {{.}}
{{/imports}}
{{#classes}}
/**
* INTERNAL: Do not use.

View File

@@ -12,21 +12,6 @@ def test_property_has_first_table_param_marked():
assert [p.param for p in prop.tableparams] == tableparams
@pytest.mark.parametrize("type,expected", [
("Foo", True),
("Bar", True),
("foo", False),
("bar", False),
(None, False),
])
def test_property_is_a_class(type, expected):
tableparams = ["a", "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
indefinite_getters = [
("Argument", "getAnArgument"),
("Element", "getAnElement"),

View File

@@ -448,7 +448,8 @@ def test_single_class_property(generate_classes, is_child, prev_child):
ql.Property(singular="Foo", type="Bar", tablename="my_objects",
tableparams=[
"this", "result"],
prev_child=prev_child, doc="foo of this my object"),
prev_child=prev_child, doc="foo of this my object",
type_is_codegen_class=True),
],
)),
"Bar.qll": (a_ql_class_public(name="Bar"), a_ql_stub(name="Bar"), a_ql_class(name="Bar", final=True, imports=[stub_import_prefix + "Bar"])),
@@ -1006,6 +1007,7 @@ def test_hideable_property(generate_classes):
final=True, properties=[
ql.Property(singular="X", type="MyObject", tablename="others",
type_is_hideable=True,
type_is_codegen_class=True,
tableparams=["this", "result"], doc="x of this other"),
])),
}

View File

@@ -33,4 +33,6 @@ codeql-extractor = { path = "../../shared/tree-sitter-extractor" }
rust-extractor-macros = { path = "macros" }
itertools = "0.13.0"
glob = "0.3.1"
chrono = { version = "0.4.38", features = ["serde"] }
serde_json = "1.0.133"
dunce = "1.0.5"

View File

@@ -45,6 +45,7 @@ pub struct Config {
pub scratch_dir: PathBuf,
pub trap_dir: PathBuf,
pub source_archive_dir: PathBuf,
pub diagnostic_dir: PathBuf,
pub cargo_target_dir: Option<PathBuf>,
pub cargo_target: Option<String>,
pub cargo_features: Vec<String>,

View File

@@ -0,0 +1,255 @@
use crate::config::Config;
use anyhow::Context;
use chrono::{DateTime, Utc};
use log::{debug, info};
use ra_ap_project_model::ProjectManifest;
use serde::ser::SerializeMap;
use serde::Serialize;
use std::collections::HashMap;
use std::fmt::Display;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::time::Instant;
#[derive(Default, Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
enum Severity {
#[default]
Note,
Warning,
Error,
}
#[derive(Default, Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "camelCase")]
struct Visibility {
status_page: bool,
cli_summary_table: bool,
telemetry: bool,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
enum Message {
TextMessage(String),
MarkdownMessage(String),
}
impl Default for Message {
fn default() -> Self {
Message::TextMessage("".to_string())
}
}
#[derive(Default, Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct Source {
id: String,
name: String,
extractor_name: String,
}
#[derive(Default, Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct Location {
file: PathBuf,
start_line: u32,
start_column: u32,
end_line: u32,
end_column: u32,
}
#[derive(Default, Debug, Clone, Serialize)]
pub struct Diagnostics<T> {
source: Source,
visibility: Visibility,
severity: Severity,
#[serde(flatten)]
message: Message,
timestamp: DateTime<Utc>,
#[serde(skip_serializing_if = "Option::is_none")]
location: Option<Location>,
attributes: T,
}
#[derive(Default, Debug, Clone, Copy, Serialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "camelCase")]
pub enum ExtractionStepKind {
#[default]
LoadManifest,
LoadSource,
Parse,
Extract,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExtractionStep {
pub action: ExtractionStepKind,
pub file: PathBuf,
pub ms: u128,
}
impl ExtractionStep {
fn new(start: Instant, action: ExtractionStepKind, file: PathBuf) -> Self {
let ret = ExtractionStep {
action,
file,
ms: start.elapsed().as_millis(),
};
debug!("{ret:?}");
ret
}
pub fn load_manifest(start: Instant, target: &ProjectManifest) -> Self {
Self::new(
start,
ExtractionStepKind::LoadManifest,
PathBuf::from(target.manifest_path()),
)
}
pub fn parse(start: Instant, target: &Path) -> Self {
Self::new(start, ExtractionStepKind::Parse, PathBuf::from(target))
}
pub fn extract(start: Instant, target: &Path) -> Self {
Self::new(start, ExtractionStepKind::Extract, PathBuf::from(target))
}
pub fn load_source(start: Instant, target: &Path) -> Self {
Self::new(start, ExtractionStepKind::LoadSource, PathBuf::from(target))
}
}
#[derive(Debug, Default, Clone)]
struct HumanReadableDuration(u128);
impl Serialize for HumanReadableDuration {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut map = serializer.serialize_map(Some(2))?;
map.serialize_entry("ms", &self.0)?;
map.serialize_entry("pretty", &self.pretty())?;
map.end()
}
}
impl HumanReadableDuration {
pub fn add(&mut self, other: u128) {
self.0 += other;
}
pub fn pretty(&self) -> String {
let milliseconds = self.0 % 1000;
let mut seconds = self.0 / 1000;
if seconds < 60 {
return format!("{seconds}.{milliseconds:03}s");
}
let mut minutes = seconds / 60;
seconds %= 60;
if minutes < 60 {
return format!("{minutes}min{seconds:02}.{milliseconds:03}s");
}
let hours = minutes / 60;
minutes %= 60;
format!("{hours}h{minutes:02}min{seconds:02}.{milliseconds:03}s")
}
}
impl From<u128> for HumanReadableDuration {
fn from(val: u128) -> Self {
HumanReadableDuration(val)
}
}
impl Display for HumanReadableDuration {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str(&self.pretty())
}
}
#[derive(Debug, Default, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct DurationsSummary {
#[serde(flatten)]
durations: HashMap<ExtractionStepKind, HumanReadableDuration>,
total: HumanReadableDuration,
}
#[derive(Debug, Default, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ExtractionSummary {
number_of_manifests: usize,
number_of_files: usize,
durations: DurationsSummary,
}
type ExtractionDiagnostics = Diagnostics<ExtractionSummary>;
fn summary(start: Instant, steps: &[ExtractionStep]) -> ExtractionSummary {
let mut number_of_manifests = 0;
let mut number_of_files = 0;
let mut durations = HashMap::new();
for step in steps {
match &step.action {
ExtractionStepKind::LoadManifest => {
number_of_manifests += 1;
}
ExtractionStepKind::Parse => {
number_of_files += 1;
}
_ => {}
}
durations
.entry(step.action)
.or_insert(HumanReadableDuration(0))
.add(step.ms);
}
let total = start.elapsed().as_millis().into();
for (key, value) in &durations {
info!("total duration ({key:?}): {value}");
}
info!("total duration: {total}");
ExtractionSummary {
number_of_manifests,
number_of_files,
durations: DurationsSummary { durations, total },
}
}
pub fn emit_extraction_diagnostics(
start: Instant,
config: &Config,
steps: &[ExtractionStep],
) -> anyhow::Result<()> {
let summary = summary(start, steps);
let diagnostics = ExtractionDiagnostics {
source: Source {
id: "rust/extractor/telemetry".to_owned(),
name: "telemetry".to_string(),
extractor_name: "rust".to_string(),
},
visibility: Visibility {
telemetry: true,
..Default::default()
},
timestamp: Utc::now(),
attributes: summary,
..Default::default()
};
std::fs::create_dir_all(&config.diagnostic_dir).with_context(|| {
format!(
"creating diagnostics directory {}",
config.diagnostic_dir.display()
)
})?;
let target = config.diagnostic_dir.join("extraction.jsonc");
let mut output = File::create(&target)
.with_context(|| format!("creating diagnostics file {}", target.display()))?;
serde_json::to_writer_pretty(&mut output, &diagnostics)
.with_context(|| format!("writing to diagnostics file {}", target.display()))?;
Ok(())
}

View File

@@ -1,2 +1,2 @@
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
top.rs aad41fc41df08b35aeca0700426e38538c23aef9030b42aeaac964dced524575 aad41fc41df08b35aeca0700426e38538c23aef9030b42aeaac964dced524575
top.rs c77ccf1e73a5b139f768e80580a261f7f3ab76823a1c9095b06f704a4912e8f1 c77ccf1e73a5b139f768e80580a261f7f3ab76823a1c9095b06f704a4912e8f1

View File

@@ -4,6 +4,15 @@
use crate::trap;
#[derive(Debug)]
pub struct File {
_unused: ()
}
impl trap::TrapClass for File {
fn class_name() -> &'static str { "File" }
}
#[derive(Debug)]
pub struct Element {
_unused: ()
@@ -13,6 +22,37 @@ impl trap::TrapClass for Element {
fn class_name() -> &'static str { "Element" }
}
#[derive(Debug)]
pub struct ExtractorStep {
pub id: trap::TrapId<ExtractorStep>,
pub action: String,
pub file: trap::Label<File>,
pub duration_ms: usize,
}
impl trap::TrapEntry for ExtractorStep {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("extractor_steps", vec![id.into(), self.action.into(), self.file.into(), self.duration_ms.into()]);
}
}
impl trap::TrapClass for ExtractorStep {
fn class_name() -> &'static str { "ExtractorStep" }
}
impl From<trap::Label<ExtractorStep>> for trap::Label<Element> {
fn from(value: trap::Label<ExtractorStep>) -> Self {
// SAFETY: this is safe because in the dbscheme ExtractorStep is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct Locatable {
_unused: ()

View File

@@ -1,13 +1,16 @@
use crate::diagnostics::{emit_extraction_diagnostics, ExtractionStep};
use crate::rust_analyzer::path_to_file_id;
use crate::trap::TrapId;
use anyhow::Context;
use archive::Archiver;
use log::info;
use log::{info, warn};
use ra_ap_hir::Semantics;
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
use ra_ap_ide_db::RootDatabase;
use ra_ap_project_model::ProjectManifest;
use ra_ap_project_model::{CargoConfig, ProjectManifest};
use ra_ap_vfs::Vfs;
use rust_analyzer::{ParseResult, RustAnalyzer};
use std::time::Instant;
use std::{
collections::HashMap,
path::{Path, PathBuf},
@@ -15,6 +18,7 @@ use std::{
mod archive;
mod config;
mod diagnostics;
pub mod generated;
mod qltest;
mod rust_analyzer;
@@ -24,18 +28,31 @@ pub mod trap;
struct Extractor<'a> {
archiver: &'a Archiver,
traps: &'a trap::TrapFileProvider,
steps: Vec<ExtractionStep>,
}
impl Extractor<'_> {
fn extract(&self, rust_analyzer: &rust_analyzer::RustAnalyzer, file: &std::path::Path) {
impl<'a> Extractor<'a> {
pub fn new(archiver: &'a Archiver, traps: &'a trap::TrapFileProvider) -> Self {
Self {
archiver,
traps,
steps: Vec::new(),
}
}
fn extract(&mut self, rust_analyzer: &rust_analyzer::RustAnalyzer, file: &std::path::Path) {
self.archiver.archive(file);
let before_parse = Instant::now();
let ParseResult {
ast,
text,
errors,
semantics_info,
} = rust_analyzer.parse(file);
self.steps.push(ExtractionStep::parse(before_parse, file));
let before_extract = Instant::now();
let line_index = LineIndex::new(text.as_ref());
let display_path = file.to_string_lossy();
let mut trap = self.traps.create("source", file);
@@ -73,22 +90,79 @@ impl Extractor<'_> {
err.to_string()
)
});
self.steps
.push(ExtractionStep::extract(before_extract, file));
}
pub fn extract_with_semantics(
&self,
&mut self,
file: &Path,
semantics: &Semantics<'_, RootDatabase>,
vfs: &Vfs,
) {
self.extract(&RustAnalyzer::new(vfs, semantics), file);
}
pub fn extract_without_semantics(&self, file: &Path, reason: &str) {
pub fn extract_without_semantics(&mut self, file: &Path, reason: &str) {
self.extract(&RustAnalyzer::WithoutSemantics { reason }, file);
}
pub fn load_manifest(
&mut self,
project: &ProjectManifest,
config: &CargoConfig,
) -> Option<(RootDatabase, Vfs)> {
let before = Instant::now();
let ret = RustAnalyzer::load_workspace(project, config);
self.steps
.push(ExtractionStep::load_manifest(before, project));
ret
}
pub fn load_source(
&mut self,
file: &Path,
semantics: &Semantics<'_, RootDatabase>,
vfs: &Vfs,
) -> Result<(), String> {
let before = Instant::now();
let Some(id) = path_to_file_id(file, vfs) else {
return Err("not included in files loaded from manifest".to_string());
};
if semantics.file_to_module_def(id).is_none() {
return Err("not included as a module".to_string());
}
self.steps.push(ExtractionStep::load_source(before, file));
Ok(())
}
pub fn emit_extraction_diagnostics(
self,
start: Instant,
cfg: &config::Config,
) -> anyhow::Result<()> {
emit_extraction_diagnostics(start, cfg, &self.steps)?;
let mut trap = self.traps.create("diagnostics", "extraction");
for step in self.steps {
let file = trap.emit_file(&step.file);
let duration_ms = usize::try_from(step.ms).unwrap_or_else(|_e| {
warn!("extraction step duration overflowed ({step:?})");
i32::MAX as usize
});
trap.emit(generated::ExtractorStep {
id: TrapId::Star,
action: format!("{:?}", step.action),
file,
duration_ms,
});
}
trap.commit()?;
Ok(())
}
}
fn main() -> anyhow::Result<()> {
let start = Instant::now();
let mut cfg = config::Config::extract().context("failed to load configuration")?;
stderrlog::new()
.module(module_path!())
@@ -103,10 +177,7 @@ fn main() -> anyhow::Result<()> {
let archiver = archive::Archiver {
root: cfg.source_archive_dir.clone(),
};
let extractor = Extractor {
archiver: &archiver,
traps: &traps,
};
let mut extractor = Extractor::new(&archiver, &traps);
let files: Vec<PathBuf> = cfg
.inputs
.iter()
@@ -132,21 +203,13 @@ fn main() -> anyhow::Result<()> {
}
let cargo_config = cfg.to_cargo_config();
for (manifest, files) in map.values().filter(|(_, files)| !files.is_empty()) {
if let Some((ref db, ref vfs)) = RustAnalyzer::load_workspace(manifest, &cargo_config) {
if let Some((ref db, ref vfs)) = extractor.load_manifest(manifest, &cargo_config) {
let semantics = Semantics::new(db);
for file in files {
let Some(id) = path_to_file_id(file, vfs) else {
extractor.extract_without_semantics(
file,
"not included in files loaded from manifest",
);
continue;
match extractor.load_source(file, &semantics, vfs) {
Ok(()) => extractor.extract_with_semantics(file, &semantics, vfs),
Err(reason) => extractor.extract_without_semantics(file, &reason),
};
if semantics.file_to_module_def(id).is_none() {
extractor.extract_without_semantics(file, "not included as a module");
continue;
}
extractor.extract_with_semantics(file, &semantics, vfs);
}
} else {
for file in files {
@@ -155,5 +218,5 @@ fn main() -> anyhow::Result<()> {
}
}
Ok(())
extractor.emit_extraction_diagnostics(start, &cfg)
}

View File

@@ -4,7 +4,6 @@ use crate::generated::{self};
use crate::rust_analyzer::FileSemanticInformation;
use crate::trap::{DiagnosticSeverity, TrapFile, TrapId};
use crate::trap::{Label, TrapClass};
use codeql_extractor::trap::{self};
use itertools::Either;
use log::Level;
use ra_ap_base_db::salsa::InternKey;
@@ -65,7 +64,7 @@ macro_rules! emit_detached {
pub struct Translator<'a> {
pub trap: TrapFile,
path: &'a str,
label: trap::Label,
label: Label<generated::File>,
line_index: LineIndex,
file_id: Option<EditionedFileId>,
pub semantics: Option<&'a Semantics<'a, RootDatabase>>,
@@ -75,7 +74,7 @@ impl<'a> Translator<'a> {
pub fn new(
trap: TrapFile,
path: &'a str,
label: trap::Label,
label: Label<generated::File>,
line_index: LineIndex,
semantic_info: Option<&FileSemanticInformation<'a>>,
) -> Translator<'a> {

View File

@@ -1,5 +1,5 @@
use crate::config;
use crate::config::Compression;
use crate::{config, generated};
use codeql_extractor::{extractor, file_paths, trap};
use log::debug;
use ra_ap_ide_db::line_index::LineCol;
@@ -138,7 +138,7 @@ pub enum DiagnosticSeverity {
impl TrapFile {
pub fn emit_location_label(
&mut self,
file_label: UntypedLabel,
file_label: Label<generated::File>,
start: LineCol,
end: LineCol,
) -> UntypedLabel {
@@ -149,7 +149,7 @@ impl TrapFile {
extractor::location_label(
&mut self.writer,
trap::Location {
file_label,
file_label: file_label.as_untyped(),
start_line,
start_column,
end_line,
@@ -159,7 +159,7 @@ impl TrapFile {
}
pub fn emit_location<E: TrapClass>(
&mut self,
file_label: UntypedLabel,
file_label: Label<generated::File>,
entity_label: Label<E>,
start: LineCol,
end: LineCol,
@@ -192,8 +192,10 @@ impl TrapFile {
],
);
}
pub fn emit_file(&mut self, absolute_path: &Path) -> trap::Label {
extractor::populate_file(&mut self.writer, absolute_path)
pub fn emit_file(&mut self, absolute_path: &Path) -> Label<generated::File> {
let untyped = extractor::populate_file(&mut self.writer, absolute_path);
// SAFETY: populate_file emits `@file` typed labels
unsafe { Label::from_untyped(untyped) }
}
pub fn label<T: TrapEntry>(&mut self, id: TrapId<T>) -> Label<T> {
@@ -243,8 +245,8 @@ impl TrapFileProvider {
})
}
pub fn create(&self, category: &str, key: &Path) -> TrapFile {
let path = file_paths::path_for(&self.trap_dir.join(category), key, "trap");
pub fn create(&self, category: &str, key: impl AsRef<Path>) -> TrapFile {
let path = file_paths::path_for(&self.trap_dir.join(category), key.as_ref(), "trap");
debug!("creating trap file {}", path.display());
let mut writer = trap::Writer::new();
extractor::populate_empty_location(&mut writer);

View File

@@ -226,6 +226,8 @@ lib/codeql/rust/elements/internal/ExternCrateImpl.qll ade4df9d3f87daf6534b8e79ff
lib/codeql/rust/elements/internal/ExternItemImpl.qll 577c8ac387c47746e3b45f943374c7ab641e8ad119e8591c31f219a5f08d3a29 bba88b974d1c03c78e0caf3d8f4118426d2aa8bd6ffd6f59a3da8ff1524a173f
lib/codeql/rust/elements/internal/ExternItemListConstructor.qll 9e4f6a036707c848c0553119272fd2b11c1740dd9910a626a9a0cf68a55b249b efde86b18bd419154fb5b6d28790a14ea989b317d84b5c1ddbdfb29c6924fd86
lib/codeql/rust/elements/internal/ExternItemListImpl.qll e89d0cf938f6e137ba1ce7907a923b1ab2be7be2fdd642c3b7a722f11b9199f8 85906d3ce89e5abc301cc96ea5104d53e90af3f5f22f8d54ec437687096e39d8
lib/codeql/rust/elements/internal/ExtractorStep.qll 1c65668007ea71d05333e44132eccc01dc2a2b4908fb37d0a73995119d3ed5f0 8cbe1eeb35bc2bc95c1b7765070d1ff58aae03fd28dc94896b091858eea40efe
lib/codeql/rust/elements/internal/ExtractorStepConstructor.qll 00c527a3139ad399ea1efd0ebe4656372d70f6c4e79136bc497a6cb84becae8e 93817f3dddeaf2c0964ab31c2df451dcee0aeba7cb6520803d8ce42cefcb3703
lib/codeql/rust/elements/internal/FieldExprConstructor.qll b3be2c4ccaf2c8a1283f3d5349d7f4f49f87b35e310ef33491023c5ab6f3abc5 645d0d4073b032f6b7284fc36a10a6ec85596fb95c68f30c09504f2c5a6f789f
lib/codeql/rust/elements/internal/FieldListImpl.qll 02a09d1d146030c68cead4614f4eef75854f19e55ed1eda60b34c4858a8d4a88 9b9f5e77546434c771d2f785119577ec46569a18473daa4169fb84a097369493
lib/codeql/rust/elements/internal/FnPtrTypeReprConstructor.qll 61d8808ea027a6e04d5304c880974332a0195451f6b4474f84b3695ec907d865 0916c63a02b01a839fe23ec8b189d37dc1b8bc4e1ba753cbf6d6f5067a46965a
@@ -455,6 +457,7 @@ lib/codeql/rust/elements/internal/generated/ExternBlock.qll c292d804a1f8d2cf6a44
lib/codeql/rust/elements/internal/generated/ExternCrate.qll 35fea4e810a896c1656adb4682c4c3bc20283768073e26ae064189ce310433c8 fc504dff79ba758d89b10cd5049539fbc766ee9862ff495066cea26abf0b5e0b
lib/codeql/rust/elements/internal/generated/ExternItem.qll 749b064ad60f32197d5b85e25929afe18e56e12f567b73e21e43e2fdf4c447e3 e2c2d423876675cf2dae399ca442aef7b2860319da9bfadeff29f2c6946f8de7
lib/codeql/rust/elements/internal/generated/ExternItemList.qll 6bc97fdae6c411cab5c501129c1d6c2321c1011cccb119515d75d07dc55c253b 6b5aa808025c0a4270cac540c07ba6faede1b3c70b8db5fd89ec5d46df9041b2
lib/codeql/rust/elements/internal/generated/ExtractorStep.qll b83ce7f18009bdd36374260652c2a8a5cd5a9b5404a1c147bbec49ad251e43f3 e6e55595300126f9c5a6fd7bde5321b2a0026b491326114d16fcc2395a1fc483
lib/codeql/rust/elements/internal/generated/FieldExpr.qll 3e506b5cb93793ec30f56bb637a600db869fcba6181b068516a671d55c362739 7bbf953696d763ad6b210f378f487ba85b875fa115b22c0c0508599a63633502
lib/codeql/rust/elements/internal/generated/FieldList.qll 43c13c6e3c9ba75a7a4cb870fc4f18752001584d48b9df0734055a6ebb789331 7c51b0b13eb02f1286d3365e53a976ba2655c4dbd8e735bc11c8b205c829e1ee
lib/codeql/rust/elements/internal/generated/FnPtrTypeRepr.qll d490ab9f2e3654d9abde18a06e534abd99ca62f518ca08670b696a97e9d5c592 01500319820f66cb4bbda6fe7c26270f76ea934efff4bb3cbf88e9b1e07e8be2
@@ -518,7 +521,7 @@ 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 c3f6352ef56aabb6bc784deafc35807b32df6f41c3bca3437221166776885c2d 3f04580798ab351e5835957379ced2b45fec628b76578c0f33f571cf03abfc83
lib/codeql/rust/elements/internal/generated/ParentChild.qll ed0af2cad8ec4d612e3c03d99548444298ae975516f2c3e909026fe5d31ab467 57801012cbe803516a093bbc0c5dcf839cb43df97a87fd2028ad2be400882c50
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
lib/codeql/rust/elements/internal/generated/Path.qll 4c1c8e840ed57880e574142b081b11d7a7428a009f10e3aa8f4645e211f6b2e0 989668cf0f1bdee7557e2f97c01e41d2a56848227fed41477833f5fc1e1d35f6
lib/codeql/rust/elements/internal/generated/PathExpr.qll 4ff4b2ab77bce1dbfddb315e7d1ff13d6fcd6bb7c30c105402f8082d05f1d337 fbc4f4e05da75ab543af33cfb620cfe09239e2574b8312f2c5bedca8a65ea6e8
@@ -531,7 +534,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 f52ff91f985848ca0e251efee1e246ae80fdca13f530df301f7090a5b18bcf13 136a84549b183d222fb6063d34d4b714b7dd42f6eb3f756894285bf405c24a22
lib/codeql/rust/elements/internal/generated/Raw.qll bcc8cfc3843e297546ba563bbd261f48863967588dbbf445bbb0894bf4539812 b8324ce13f8a5fffdcf2c24ca6f685ac11d959eb3139bdc6f89430c83dd6ddfd
lib/codeql/rust/elements/internal/generated/RecordExpr.qll eb6cb662e463f9260efae1a6ce874fa781172063b916ef1963f861e9942d308d 1a21cbccc8f3799ff13281e822818ebfb21d81591720a427cac3625512cb9d40
lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1
lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0
@@ -557,8 +560,8 @@ lib/codeql/rust/elements/internal/generated/Static.qll ea22838e0b7d9796dfaf5deda
lib/codeql/rust/elements/internal/generated/Stmt.qll 8473ff532dd5cc9d7decaddcd174b94d610f6ca0aec8e473cc051dad9f3db917 6ef7d2b5237c2dbdcacbf7d8b39109d4dc100229f2b28b5c9e3e4fbf673ba72b
lib/codeql/rust/elements/internal/generated/StmtList.qll a667193e32341e17400867c6e359878c4e645ef9f5f4d97676afc0283a33a026 a320ed678ee359302e2fc1b70a9476705cd616fcfa44a499d32f0c7715627f73
lib/codeql/rust/elements/internal/generated/Struct.qll 4d57f0db12dc7ad3e31e750a24172ef1505406b4dab16386af0674bd18bf8f4b 1a73c83df926b996f629316f74c61ea775be04532ab61b56af904223354f033e
lib/codeql/rust/elements/internal/generated/Synth.qll 0bb53e7d628fcd74a28fb7b00c51dc7f212a775894a4dc485a68089a7c02d766 6c031f7c95974521f17d6fedd429d35a1aea142b7cef5123f34504a79c21670b
lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 8f7f08d1599e2dcbe553a7e4428a8787cef76b1d12b88f1b5925a4c59d617fae 8f7f08d1599e2dcbe553a7e4428a8787cef76b1d12b88f1b5925a4c59d617fae
lib/codeql/rust/elements/internal/generated/Synth.qll 839aa6b03b461ed9c79192d905969c63c99e7a12074e3487e74d2163d20ee499 44b8caba3186aaeb6d6b5759610627f8bc791e62001acfd1a66324086c17536f
lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 3ceb5f6ee40b94955ce5f47feb454cc9129941aad3cdbe6e337bbe41e76a8a23 3ceb5f6ee40b94955ce5f47feb454cc9129941aad3cdbe6e337bbe41e76a8a23
lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b
lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c
lib/codeql/rust/elements/internal/generated/Trait.qll 8fa41b50fa0f68333534f2b66bb4ec8e103ff09ac8fa5c2cc64bc04beafec205 ce1c9aa6d0e2f05d28aab8e1165c3b9fb8e24681ade0cf6a9df2e8617abeae7e
@@ -592,7 +595,7 @@ lib/codeql/rust/elements/internal/generated/WhileExpr.qll 7edf1f23fbf953a2baabcd
lib/codeql/rust/elements/internal/generated/WildcardPat.qll d74b70b57a0a66bfae017a329352a5b27a6b9e73dd5521d627f680e810c6c59e 4b913b548ba27ff3c82fcd32cf996ff329cb57d176d3bebd0fcef394486ea499
lib/codeql/rust/elements/internal/generated/YeetExpr.qll cac328200872a35337b4bcb15c851afb4743f82c080f9738d295571eb01d7392 94af734eea08129b587fed849b643e7572800e8330c0b57d727d41abda47930b
lib/codeql/rust/elements/internal/generated/YieldExpr.qll 37e5f0c1e373a22bbc53d8b7f2c0e1f476e5be5080b8437c5e964f4e83fad79a 4a9a68643401637bf48e5c2b2f74a6bf0ddcb4ff76f6bffb61d436b685621e85
lib/codeql/rust/elements.qll 35959f2de54b6ee534fc592e1928c0829aa6e881e281a5acf724c10e4c685070 35959f2de54b6ee534fc592e1928c0829aa6e881e281a5acf724c10e4c685070
lib/codeql/rust/elements.qll a055d1f5bf70c9f8f6d5e34087146e813f3452b225b07b64f087d6e61f52a3b3 a055d1f5bf70c9f8f6d5e34087146e813f3452b225b07b64f087d6e61f52a3b3
test/extractor-tests/generated/Abi/Abi.ql 7f6e7dc4af86eca3ebdc79b10373988cd0871bd78b51997d3cffd969105e5fdd 2f936b6ca005c6157c755121584410c03e4a3949c23bee302fbe05ee10ce118f
test/extractor-tests/generated/Abi/Abi_getAbiString.ql a496762fcec5a0887b87023bbf93e9b650f02e20113e25c44d6e4281ae8f5335 14109c7ce11ba25e3cd6e7f1b3fcb4cb00622f2a4eac91bfe43145c5f366bc52
test/extractor-tests/generated/ArgList/ArgList.ql e412927756e72165d0e7c5c9bd3fca89d08197bbf760db8fb7683c64bb2229bc 043dba8506946fbb87753e22c387987d7eded6ddb963aa067f9e60ef9024d684

3
rust/ql/.gitattributes generated vendored
View File

@@ -228,6 +228,8 @@
/lib/codeql/rust/elements/internal/ExternItemImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/ExternItemListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ExternItemListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/ExtractorStep.qll linguist-generated
/lib/codeql/rust/elements/internal/ExtractorStepConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/FieldExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/FieldListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/FnPtrTypeReprConstructor.qll linguist-generated
@@ -457,6 +459,7 @@
/lib/codeql/rust/elements/internal/generated/ExternCrate.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/ExternItem.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/ExternItemList.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/ExtractorStep.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/FieldExpr.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/FieldList.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/FnPtrTypeRepr.qll linguist-generated

View File

@@ -9,13 +9,26 @@ def cargo(cwd):
assert (cwd / "Cargo.toml").exists()
(cwd / "rust-project.json").unlink(missing_ok=True)
@pytest.fixture(scope="session")
def rust_sysroot_src() -> str:
rust_sysroot = pathlib.Path(commands.run("rustc --print sysroot", _capture=True))
ret = rust_sysroot.joinpath("lib", "rustlib", "src", "rust", "library")
assert ret.exists()
return str(ret)
@pytest.fixture
def rust_project(cwd):
def rust_project(cwd, rust_sysroot_src):
project_file = cwd / "rust-project.json"
assert project_file.exists()
rust_sysroot = pathlib.Path(commands.run("rustc --print sysroot", _capture=True))
project = json.loads(project_file.read_text())
project["sysroot_src"] = str(rust_sysroot.joinpath("lib", "rustlib", "src", "rust", "library"))
project["sysroot_src"] = rust_sysroot_src
project_file.write_text(json.dumps(project, indent=4))
(cwd / "Cargo.toml").unlink(missing_ok=True)
@pytest.fixture
def rust_check_diagnostics(check_diagnostics):
check_diagnostics.redact += [
"attributes.durations.*.ms",
"attributes.durations.*.pretty",
]
return check_diagnostics

View File

@@ -0,0 +1,39 @@
{
"attributes": {
"durations": {
"extract": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"loadManifest": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"loadSource": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"parse": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"total": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
}
},
"numberOfFiles": 5,
"numberOfManifests": 1
},
"severity": "note",
"source": {
"extractorName": "rust",
"id": "rust/extractor/telemetry",
"name": "telemetry"
},
"visibility": {
"cliSummaryTable": false,
"statusPage": false,
"telemetry": true
}
}

View File

@@ -0,0 +1,15 @@
| Cargo.toml:0:0:0:0 | LoadManifest(Cargo.toml) |
| src/directory_module/mod.rs:0:0:0:0 | Extract(src/directory_module/mod.rs) |
| src/directory_module/mod.rs:0:0:0:0 | LoadSource(src/directory_module/mod.rs) |
| src/directory_module/mod.rs:0:0:0:0 | Parse(src/directory_module/mod.rs) |
| src/directory_module/nested_module.rs:0:0:0:0 | Extract(src/directory_module/nested_module.rs) |
| src/directory_module/nested_module.rs:0:0:0:0 | LoadSource(src/directory_module/nested_module.rs) |
| src/directory_module/nested_module.rs:0:0:0:0 | Parse(src/directory_module/nested_module.rs) |
| src/directory_module/not_loaded.rs:0:0:0:0 | Extract(src/directory_module/not_loaded.rs) |
| src/directory_module/not_loaded.rs:0:0:0:0 | Parse(src/directory_module/not_loaded.rs) |
| src/file_module.rs:0:0:0:0 | Extract(src/file_module.rs) |
| src/file_module.rs:0:0:0:0 | LoadSource(src/file_module.rs) |
| src/file_module.rs:0:0:0:0 | Parse(src/file_module.rs) |
| src/main.rs:0:0:0:0 | Extract(src/main.rs) |
| src/main.rs:0:0:0:0 | LoadSource(src/main.rs) |
| src/main.rs:0:0:0:0 | Parse(src/main.rs) |

View File

@@ -0,0 +1,4 @@
import codeql.rust.elements.internal.ExtractorStep
from ExtractorStep step
select step

View File

@@ -0,0 +1,15 @@
| rust-project.json:0:0:0:0 | LoadManifest(rust-project.json) |
| src/directory_module/mod.rs:0:0:0:0 | Extract(src/directory_module/mod.rs) |
| src/directory_module/mod.rs:0:0:0:0 | LoadSource(src/directory_module/mod.rs) |
| src/directory_module/mod.rs:0:0:0:0 | Parse(src/directory_module/mod.rs) |
| src/directory_module/nested_module.rs:0:0:0:0 | Extract(src/directory_module/nested_module.rs) |
| src/directory_module/nested_module.rs:0:0:0:0 | LoadSource(src/directory_module/nested_module.rs) |
| src/directory_module/nested_module.rs:0:0:0:0 | Parse(src/directory_module/nested_module.rs) |
| src/directory_module/not_loaded.rs:0:0:0:0 | Extract(src/directory_module/not_loaded.rs) |
| src/directory_module/not_loaded.rs:0:0:0:0 | Parse(src/directory_module/not_loaded.rs) |
| src/file_module.rs:0:0:0:0 | Extract(src/file_module.rs) |
| src/file_module.rs:0:0:0:0 | LoadSource(src/file_module.rs) |
| src/file_module.rs:0:0:0:0 | Parse(src/file_module.rs) |
| src/main.rs:0:0:0:0 | Extract(src/main.rs) |
| src/main.rs:0:0:0:0 | LoadSource(src/main.rs) |
| src/main.rs:0:0:0:0 | Parse(src/main.rs) |

View File

@@ -1,4 +1,4 @@
| Elements extracted | 50 |
| Elements extracted | 65 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 1 |

View File

@@ -1,5 +1,10 @@
def test_cargo(codeql, rust, cargo, check_source_archive):
import pytest
@pytest.mark.ql_test("steps.ql", expected=".cargo.expected")
def test_cargo(codeql, rust, cargo, check_source_archive, rust_check_diagnostics):
codeql.database.create()
def test_rust_project(codeql, rust, rust_project, check_source_archive):
@pytest.mark.ql_test("steps.ql", expected=".rust-project.expected")
def test_rust_project(codeql, rust, rust_project, check_source_archive, rust_check_diagnostics):
codeql.database.create()

View File

@@ -0,0 +1,39 @@
{
"attributes": {
"durations": {
"extract": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"loadManifest": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"loadSource": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"parse": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"total": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
}
},
"numberOfFiles": 4,
"numberOfManifests": 2
},
"severity": "note",
"source": {
"extractorName": "rust",
"id": "rust/extractor/telemetry",
"name": "telemetry"
},
"visibility": {
"cliSummaryTable": false,
"statusPage": false,
"telemetry": true
}
}

View File

@@ -0,0 +1,39 @@
{
"attributes": {
"durations": {
"extract": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"loadManifest": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"loadSource": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"parse": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"total": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
}
},
"numberOfFiles": 4,
"numberOfManifests": 1
},
"severity": "note",
"source": {
"extractorName": "rust",
"id": "rust/extractor/telemetry",
"name": "telemetry"
},
"visibility": {
"cliSummaryTable": false,
"statusPage": false,
"telemetry": true
}
}

View File

@@ -0,0 +1,14 @@
| exe/Cargo.toml:0:0:0:0 | LoadManifest(exe/Cargo.toml) |
| exe/src/a_module.rs:0:0:0:0 | Extract(exe/src/a_module.rs) |
| exe/src/a_module.rs:0:0:0:0 | LoadSource(exe/src/a_module.rs) |
| exe/src/a_module.rs:0:0:0:0 | Parse(exe/src/a_module.rs) |
| exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) |
| exe/src/main.rs:0:0:0:0 | LoadSource(exe/src/main.rs) |
| exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) |
| lib/Cargo.toml:0:0:0:0 | LoadManifest(lib/Cargo.toml) |
| lib/src/a_module/mod.rs:0:0:0:0 | Extract(lib/src/a_module/mod.rs) |
| lib/src/a_module/mod.rs:0:0:0:0 | LoadSource(lib/src/a_module/mod.rs) |
| lib/src/a_module/mod.rs:0:0:0:0 | Parse(lib/src/a_module/mod.rs) |
| lib/src/lib.rs:0:0:0:0 | Extract(lib/src/lib.rs) |
| lib/src/lib.rs:0:0:0:0 | LoadSource(lib/src/lib.rs) |
| lib/src/lib.rs:0:0:0:0 | Parse(lib/src/lib.rs) |

View File

@@ -0,0 +1,4 @@
import codeql.rust.elements.internal.ExtractorStep
from ExtractorStep step
select step

View File

@@ -0,0 +1,13 @@
| exe/src/a_module.rs:0:0:0:0 | Extract(exe/src/a_module.rs) |
| exe/src/a_module.rs:0:0:0:0 | LoadSource(exe/src/a_module.rs) |
| exe/src/a_module.rs:0:0:0:0 | Parse(exe/src/a_module.rs) |
| exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) |
| exe/src/main.rs:0:0:0:0 | LoadSource(exe/src/main.rs) |
| exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) |
| lib/src/a_module/mod.rs:0:0:0:0 | Extract(lib/src/a_module/mod.rs) |
| lib/src/a_module/mod.rs:0:0:0:0 | LoadSource(lib/src/a_module/mod.rs) |
| lib/src/a_module/mod.rs:0:0:0:0 | Parse(lib/src/a_module/mod.rs) |
| lib/src/lib.rs:0:0:0:0 | Extract(lib/src/lib.rs) |
| lib/src/lib.rs:0:0:0:0 | LoadSource(lib/src/lib.rs) |
| lib/src/lib.rs:0:0:0:0 | Parse(lib/src/lib.rs) |
| rust-project.json:0:0:0:0 | LoadManifest(rust-project.json) |

View File

@@ -1,4 +1,4 @@
| Elements extracted | 72 |
| Elements extracted | 86 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 0 |

View File

@@ -0,0 +1,17 @@
| Elements extracted | 85 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 0 |
| Files extracted - total | 4 |
| Files extracted - with errors | 0 |
| Files extracted - without errors | 4 |
| Inconsistencies - AST | 0 |
| Inconsistencies - CFG | 0 |
| Inconsistencies - data flow | 0 |
| Lines of code extracted | 9 |
| Lines of user code extracted | 9 |
| Macro calls - resolved | 2 |
| Macro calls - total | 2 |
| Macro calls - unresolved | 0 |
| Taint sources - active | 0 |
| Taint sources - total | 0 |

View File

@@ -1,5 +1,14 @@
def test_cargo(codeql, rust, cargo, check_source_archive):
import pytest
@pytest.mark.ql_test("steps.ql", expected=".cargo.expected")
@pytest.mark.ql_test("summary.qlref", expected=".cargo.expected")
def test_cargo(codeql, rust, cargo, check_source_archive, rust_check_diagnostics):
rust_check_diagnostics.expected_suffix = ".cargo.expected"
codeql.database.create()
def test_rust_project(codeql, rust, rust_project, check_source_archive):
@pytest.mark.ql_test("steps.ql", expected=".rust-project.expected")
@pytest.mark.ql_test("summary.qlref", expected=".rust-project.expected")
def test_rust_project(codeql, rust, rust_project, check_source_archive, rust_check_diagnostics):
rust_check_diagnostics.expected_suffix = ".rust-project.expected"
codeql.database.create()

View File

@@ -6,6 +6,7 @@ private import codeql.rust.elements.SourceFile
private import codeql.rust.elements.AstNode
private import codeql.rust.elements.Comment
private import codeql.rust.Diagnostics
private import codeql.rust.elements.internal.ExtractorStep
private module Input implements InputSig {
abstract class ContainerBase extends @container {
@@ -36,7 +37,9 @@ class Folder = Impl::Folder;
/** A file. */
class File extends Container, Impl::File {
/** Holds if this file was extracted from ordinary source code. */
predicate fromSource() { any() }
predicate fromSource() {
exists(ExtractorStep s | s.getAction() = "Extract" and s.getFile() = this)
}
/**
* Gets the number of lines containing code in this file. This value
@@ -58,11 +61,20 @@ class File extends Container, Impl::File {
}
}
/**
* A source file that was extracted.
*
* TODO: rename `SourceFile` from the generated AST to give that name to this class.
*/
class ExtractedFile extends File {
ExtractedFile() { this.fromSource() }
}
/**
* A successfully extracted file, that is, a file that was extracted and
* contains no extraction errors or warnings.
*/
class SuccessfullyExtractedFile extends File {
class SuccessfullyExtractedFile extends ExtractedFile {
SuccessfullyExtractedFile() {
not exists(Diagnostic d |
d.getLocation().getFile() = this and

View File

@@ -3,6 +3,7 @@
* This module exports all modules providing `Element` subclasses.
*/
import codeql.files.FileSystem
import codeql.rust.elements.Abi
import codeql.rust.elements.Addressable
import codeql.rust.elements.ArgList

View File

@@ -0,0 +1,13 @@
// generated by codegen, do not edit
/**
* This module provides the class `ExtractorStep`.
*/
private import ExtractorStepImpl
import codeql.rust.elements.Element
import codeql.files.FileSystem
/**
* INTERNAL: Do not use.
*/
final class ExtractorStep = Impl::ExtractorStep;

View File

@@ -0,0 +1,14 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `ExtractorStep` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.Raw
/**
* The characteristic predicate of `ExtractorStep` synthesized instances.
* INTERNAL: Do not use.
*/
predicate constructExtractorStep(Raw::ExtractorStep id) { any() }

View File

@@ -0,0 +1,32 @@
/**
* This module provides a hand-modifiable wrapper around the generated class `ExtractorStep`.
*
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.ExtractorStep
/**
* INTERNAL: This module contains the customizable definition of `ExtractorStep` and should not
* be referenced directly.
*/
module Impl {
class ExtractorStep extends Generated::ExtractorStep {
override string toString() {
result = this.getAction() + "(" + this.getFile().getAbsolutePath() + ")"
}
/**
* Provides location information for this step.
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getFile().getAbsolutePath() = filepath and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}
}

View File

@@ -0,0 +1,45 @@
// generated by codegen, do not edit
/**
* This module provides the generated definition of `ExtractorStep`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.internal.ElementImpl::Impl as ElementImpl
import codeql.files.FileSystem
/**
* INTERNAL: This module contains the fully generated definition of `ExtractorStep` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::ExtractorStep` class directly.
* Use the subclass `ExtractorStep`, where the following predicates are available.
*/
class ExtractorStep extends Synth::TExtractorStep, ElementImpl::Element {
override string getAPrimaryQlClass() { result = "ExtractorStep" }
/**
* Gets the action of this extractor step.
*/
string getAction() {
result = Synth::convertExtractorStepToRaw(this).(Raw::ExtractorStep).getAction()
}
/**
* Gets the file of this extractor step.
*/
File getFile() {
result = Synth::convertExtractorStepToRaw(this).(Raw::ExtractorStep).getFile()
}
/**
* Gets the duration ms of this extractor step.
*/
int getDurationMs() {
result = Synth::convertExtractorStepToRaw(this).(Raw::ExtractorStep).getDurationMs()
}
}
}

View File

@@ -5,12 +5,28 @@
import codeql.rust.elements
import codeql.rust.elements.internal.ArrayExprInternal
import codeql.rust.elements.internal.ExtractorStep
private module Impl {
private Element getImmediateChildOfElement(Element e, int index, string partialPredicateCall) {
none()
}
private Element getImmediateChildOfExtractorStep(
ExtractorStep e, int index, string partialPredicateCall
) {
exists(int b, int bElement, int n |
b = 0 and
bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and
n = bElement and
(
none()
or
result = getImmediateChildOfElement(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfLocatable(Locatable e, int index, string partialPredicateCall) {
exists(int b, int bElement, int n |
b = 0 and
@@ -3705,6 +3721,8 @@ private module Impl {
// * none() simplifies generation, as we can append `or ...` without a special case for the first item
none()
or
result = getImmediateChildOfExtractorStep(e, index, partialAccessor)
or
result = getImmediateChildOfFormat(e, index, partialAccessor)
or
result = getImmediateChildOfFormatArgument(e, index, partialAccessor)

View File

@@ -3,6 +3,8 @@
* This module holds thin fully generated class definitions around DB entities.
*/
module Raw {
private import codeql.files.FileSystem
/**
* INTERNAL: Do not use.
*/
@@ -10,6 +12,28 @@ module Raw {
string toString() { none() }
}
/**
* INTERNAL: Do not use.
*/
class ExtractorStep extends @extractor_step, Element {
override string toString() { result = "ExtractorStep" }
/**
* Gets the action of this extractor step.
*/
string getAction() { extractor_steps(this, result, _, _) }
/**
* Gets the file of this extractor step.
*/
File getFile() { extractor_steps(this, _, result, _) }
/**
* Gets the duration ms of this extractor step.
*/
int getDurationMs() { extractor_steps(this, _, _, result) }
}
/**
* INTERNAL: Do not use.
*/

View File

@@ -142,6 +142,10 @@ module Synth {
* INTERNAL: Do not use.
*/
TExternItemList(Raw::ExternItemList id) { constructExternItemList(id) } or
/**
* INTERNAL: Do not use.
*/
TExtractorStep(Raw::ExtractorStep id) { constructExtractorStep(id) } or
/**
* INTERNAL: Do not use.
*/
@@ -953,6 +957,12 @@ module Synth {
*/
TExternItemList convertExternItemListFromRaw(Raw::Element e) { result = TExternItemList(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TExtractorStep`, if possible.
*/
TExtractorStep convertExtractorStepFromRaw(Raw::Element e) { result = TExtractorStep(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TFieldExpr`, if possible.
@@ -1842,6 +1852,8 @@ module Synth {
* Converts a raw DB element to a synthesized `TElement`, if possible.
*/
TElement convertElementFromRaw(Raw::Element e) {
result = convertExtractorStepFromRaw(e)
or
result = convertLocatableFromRaw(e)
or
result = convertUnextractedFromRaw(e)
@@ -2367,6 +2379,12 @@ module Synth {
*/
Raw::Element convertExternItemListToRaw(TExternItemList e) { e = TExternItemList(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TExtractorStep` to a raw DB element, if possible.
*/
Raw::Element convertExtractorStepToRaw(TExtractorStep e) { e = TExtractorStep(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFieldExpr` to a raw DB element, if possible.
@@ -3254,6 +3272,8 @@ module Synth {
* Converts a synthesized `TElement` to a raw DB element, if possible.
*/
Raw::Element convertElementToRaw(TElement e) {
result = convertExtractorStepToRaw(e)
or
result = convertLocatableToRaw(e)
or
result = convertUnextractedToRaw(e)

View File

@@ -35,6 +35,7 @@ import codeql.rust.elements.internal.ExprStmtConstructor
import codeql.rust.elements.internal.ExternBlockConstructor
import codeql.rust.elements.internal.ExternCrateConstructor
import codeql.rust.elements.internal.ExternItemListConstructor
import codeql.rust.elements.internal.ExtractorStepConstructor
import codeql.rust.elements.internal.FieldExprConstructor
import codeql.rust.elements.internal.FnPtrTypeReprConstructor
import codeql.rust.elements.internal.ForExprConstructor

View File

@@ -120,10 +120,18 @@ locatable_locations(
// from schema
@element =
@locatable
@extractor_step
| @locatable
| @unextracted
;
extractor_steps(
unique int id: @extractor_step,
string action: string ref,
int file: @file ref,
int duration_ms: int ref
);
@locatable =
@ast_node
;

View File

@@ -8,6 +8,6 @@
import rust
from File f
from ExtractedFile f
where exists(f.getRelativePath())
select f, "File successfully extracted."

View File

@@ -11,7 +11,7 @@ import codeql.files.FileSystem
/** Gets the SARIF severity to associate with an error. */
int getSeverity() { result = 2 }
from ExtractionError error, File f
from ExtractionError error, ExtractedFile f
where
f = error.getLocation().getFile() and
exists(f.getRelativePath())

View File

@@ -21,10 +21,13 @@ where
or
key = "Extraction warnings" and value = count(ExtractionWarning w)
or
key = "Files extracted - total" and value = count(File f | exists(f.getRelativePath()))
key = "Files extracted - total" and value = count(ExtractedFile f | exists(f.getRelativePath()))
or
key = "Files extracted - with errors" and
value = count(File f | exists(f.getRelativePath()) and not f instanceof SuccessfullyExtractedFile)
value =
count(ExtractedFile f |
exists(f.getRelativePath()) and not f instanceof SuccessfullyExtractedFile
)
or
key = "Files extracted - without errors" and
value = count(SuccessfullyExtractedFile f | exists(f.getRelativePath()))

View File

@@ -1,3 +1,4 @@
| a_file.rs:0:0:0:0 | a_file.rs |
| another_file.rs:0:0:0:0 | another_file.rs |
| lib.rs:0:0:0:0 | lib.rs |
| Cargo.toml:0:0:0:0 | Cargo.toml | fromSource: no |
| a_file.rs:0:0:0:0 | a_file.rs | fromSource: yes |
| another_file.rs:0:0:0:0 | another_file.rs | fromSource: yes |
| lib.rs:0:0:0:0 | lib.rs | fromSource: yes |

View File

@@ -1,5 +1,7 @@
import rust
from File f
where exists(f.getRelativePath())
select f
from File f, string fromSource
where
exists(f.getRelativePath()) and
if f.fromSource() then fromSource = "fromSource: yes" else fromSource = "fromSource: no"
select f, fromSource

View File

@@ -5,4 +5,3 @@
| main.rs:0:0:0:0 | main.rs | File successfully extracted. |
| my_macro.rs:0:0:0:0 | my_macro.rs | File successfully extracted. |
| my_struct.rs:0:0:0:0 | my_struct.rs | File successfully extracted. |
| options.yml:0:0:0:0 | options.yml | File successfully extracted. |

View File

@@ -5,4 +5,5 @@
| lib.rs:0:0:0:0 | lib.rs | 5 |
| does_not_compile.rs:0:0:0:0 | does_not_compile.rs | 3 |
| error.rs:0:0:0:0 | error.rs | 3 |
| Cargo.toml:0:0:0:0 | Cargo.toml | 0 |
| options.yml:0:0:0:0 | options.yml | 0 |

View File

@@ -1,10 +1,10 @@
| Elements extracted | 382 |
| Elements extracted | 404 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 7 |
| Files extracted - total | 8 |
| Files extracted - total | 7 |
| Files extracted - with errors | 3 |
| Files extracted - without errors | 5 |
| Files extracted - without errors | 4 |
| Inconsistencies - AST | 0 |
| Inconsistencies - CFG | 0 |
| Inconsistencies - data flow | 0 |

View File

@@ -3,6 +3,7 @@ from misc.codegen.lib.schemadefs import *
include("../shared/tree-sitter-extractor/src/generator/prefix.dbscheme")
include("prefix.dbscheme")
File = imported("File", "codeql.files.FileSystem")
@qltest.skip
class Element:
@@ -93,3 +94,11 @@ class Resolvable(AstNode):
"""
resolved_path: optional[string] | rust.detach | ql.internal
resolved_crate_origin: optional[string] | rust.detach | ql.internal
@qltest.skip
@ql.internal
class ExtractorStep(Element):
action: string
file: File
duration_ms: int

View File

@@ -712,7 +712,7 @@ lib/codeql/swift/generated/OtherAvailabilitySpec.qll d9feaa2a71acff3184ca389045b
lib/codeql/swift/generated/ParentChild.qll d1814f2bad4c2ba9242ce49fe6fb8564ac99fc1fd3a7d12aa55e5c6dd7bb529b 1a2075b731d07a5e3c6a69d001796c8de925069d839671a294c9cba6c3db724a
lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll dc17b49a90a18a8f7607adf2433bc8f0c194fa3e803aa3822f809d4d4fbd6793 be48ea9f8ae17354c8508aaed24337a9e57ce01f288fece3dcecd99776cabcec
lib/codeql/swift/generated/PureSynthConstructors.qll bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4 bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4
lib/codeql/swift/generated/Raw.qll 118b43fedd4265b5aa15c33ef01a2f5a5db6e5597f95bef1078a01c3ff8da983 075aec2c8b232f0361ebf63f07ae9b66163f3975e6023583fb0fa2e40b979a33
lib/codeql/swift/generated/Raw.qll a47950495630c10c00afee734d779e5e3e7f8e3e65ae3f04b9a1254e3e73921e 075aec2c8b232f0361ebf63f07ae9b66163f3975e6023583fb0fa2e40b979a33
lib/codeql/swift/generated/Synth.qll 31e318c6e156848c85a2a2664695b48b5e93c57c9bb22fa29d027069907b3ab0 8655ffcf772f55284b93f1d7f8e1b3d497a9744d5f2e0c17bc322c1fdf8bdba8
lib/codeql/swift/generated/SynthConstructors.qll 3e53c7853096020219c01dae85681fe80b34938d198a0ff359a209dda41c5ed7 3e53c7853096020219c01dae85681fe80b34938d198a0ff359a209dda41c5ed7
lib/codeql/swift/generated/UnknownFile.qll 247ddf2ebb49ce5ed4bf7bf91a969ddff37de6c78d43d8affccaf7eb586e06f2 452b29f0465ef45e978ef8b647b75e5a2a1e53f2a568fc003bc8f52f73b3fa4d