mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Rust: generate test code from schema docstrings
This generates test source files from code blocks in class docstrings.
By default the test code is generated as is, but it can optionally:
* be wrapped in a function providing an adequate context using
`@rust.doc_test_function(name, *, lifetimes=(), return_type="()", **kwargs)`,
with `kwargs` providing both generic and normal params depending on
capitalization
* be skipped altogether using `@rust.skip_doc_test`
So for example an annotation like
```python
@rust.doc_test_function("foo",
lifetimes=("a",),
T="Eq",
x="&'a T",
y="&'a T",
return_type="&'a T")
```
will result in the following wrapper:
```rust
fn foo<'a, T: Eq>(x: &'a T, y: &'a T) -> &'a T {
// example code here
}
```
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from . import dbschemegen, qlgen, trapgen, cppgen, rustgen
|
||||
from . import dbschemegen, trapgen, cppgen, rustgen, rusttestgen, qlgen
|
||||
|
||||
|
||||
def generate(target, opts, renderer):
|
||||
|
||||
@@ -287,7 +287,7 @@ def _is_under_qltest_collapsed_hierarchy(cls: schema.Class, lookup: typing.Dict[
|
||||
_is_in_qltest_collapsed_hierarchy(lookup[b], lookup) for b in cls.bases)
|
||||
|
||||
|
||||
def _should_skip_qltest(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
def should_skip_qltest(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_skip" in cls.pragmas or not (
|
||||
cls.final or "qltest_collapse_hierarchy" in cls.pragmas) or _is_under_qltest_collapsed_hierarchy(
|
||||
cls, lookup)
|
||||
@@ -413,7 +413,7 @@ def generate(opts, renderer):
|
||||
|
||||
if test_out:
|
||||
for c in data.classes.values():
|
||||
if _should_skip_qltest(c, data.classes):
|
||||
if should_skip_qltest(c, data.classes):
|
||||
continue
|
||||
test_with = data.classes[c.test_with] if c.test_with else c
|
||||
test_dir = test_out / test_with.group / test_with.name
|
||||
|
||||
@@ -86,20 +86,24 @@ def generate(opts, renderer):
|
||||
processor = Processor(schemaloader.load_file(opts.schema))
|
||||
out = opts.rust_output
|
||||
groups = set()
|
||||
for group, classes in processor.get_classes().items():
|
||||
group = group or "top"
|
||||
groups.add(group)
|
||||
with renderer.manage(generated=out.rglob("*.rs"),
|
||||
stubs=(),
|
||||
registry=opts.generated_registry,
|
||||
force=opts.force) as renderer:
|
||||
for group, classes in processor.get_classes().items():
|
||||
group = group or "top"
|
||||
groups.add(group)
|
||||
renderer.render(
|
||||
rust.ClassList(
|
||||
classes,
|
||||
opts.schema,
|
||||
),
|
||||
out / f"{group}.rs",
|
||||
)
|
||||
renderer.render(
|
||||
rust.ClassList(
|
||||
classes,
|
||||
rust.ModuleList(
|
||||
groups,
|
||||
opts.schema,
|
||||
),
|
||||
out / f"{group}.rs",
|
||||
out / f"mod.rs",
|
||||
)
|
||||
renderer.render(
|
||||
rust.ModuleList(
|
||||
groups,
|
||||
opts.schema,
|
||||
),
|
||||
out / f"mod.rs",
|
||||
)
|
||||
|
||||
70
misc/codegen/generators/rusttestgen.py
Normal file
70
misc/codegen/generators/rusttestgen.py
Normal file
@@ -0,0 +1,70 @@
|
||||
import dataclasses
|
||||
import typing
|
||||
|
||||
from misc.codegen.loaders import schemaloader
|
||||
from . import qlgen
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Param:
|
||||
name: str
|
||||
type: str
|
||||
first: bool = False
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Function:
|
||||
name: str
|
||||
generic_params: list[Param]
|
||||
params: list[Param]
|
||||
return_type: str
|
||||
|
||||
def __post_init__(self):
|
||||
if self.generic_params:
|
||||
self.generic_params[0].first = True
|
||||
if self.params:
|
||||
self.params[0].first = True
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TestCode:
|
||||
template: typing.ClassVar[str] = "rust_test_code"
|
||||
|
||||
code: str
|
||||
function: Function | None = None
|
||||
|
||||
|
||||
def generate(opts, renderer):
|
||||
assert opts.ql_test_output
|
||||
schema = schemaloader.load_file(opts.schema)
|
||||
with renderer.manage(generated=opts.ql_test_output.rglob("gen_*.rs"),
|
||||
stubs=(),
|
||||
registry=opts.generated_registry,
|
||||
force=opts.force) as renderer:
|
||||
for cls in schema.classes.values():
|
||||
if (qlgen.should_skip_qltest(cls, schema.classes) or
|
||||
"rust_skip_test_from_doc" in cls.pragmas or
|
||||
not cls.doc
|
||||
):
|
||||
continue
|
||||
fn = cls.rust_doc_test_function
|
||||
if fn:
|
||||
generic_params = [Param(k, v) for k, v in fn.params.items() if k[0].isupper() or k[0] == "'"]
|
||||
params = [Param(k, v) for k, v in fn.params.items() if k[0].islower()]
|
||||
fn = Function(fn.name, generic_params, params, fn.return_type)
|
||||
code = []
|
||||
adding_code = False
|
||||
for line in cls.doc:
|
||||
match line, adding_code:
|
||||
case "```", _:
|
||||
adding_code = not adding_code
|
||||
case _, False:
|
||||
code.append(f"// {line}")
|
||||
case _, True:
|
||||
code.append(line)
|
||||
if fn:
|
||||
indent = 4 * " "
|
||||
code = [indent + l for l in code]
|
||||
test_with = schema.classes[cls.test_with] if cls.test_with else cls
|
||||
test = opts.ql_test_output / test_with.group / test_with.name / f"gen_{cls.name.lower()}.rs"
|
||||
renderer.render(TestCode(code="\n".join(code), function=fn), test)
|
||||
@@ -94,6 +94,7 @@ class Class:
|
||||
default_doc_name: Optional[str] = None
|
||||
hideable: bool = False
|
||||
test_with: Optional[str] = None
|
||||
rust_doc_test_function: Optional["FunctionInfo"] = None # TODO: parametrized pragmas
|
||||
|
||||
@property
|
||||
def final(self):
|
||||
@@ -202,3 +203,10 @@ def split_doc(doc):
|
||||
while trimmed and not trimmed[0]:
|
||||
trimmed.pop(0)
|
||||
return trimmed
|
||||
|
||||
|
||||
@dataclass
|
||||
class FunctionInfo:
|
||||
name: str
|
||||
params: dict[str, str]
|
||||
return_type: str
|
||||
|
||||
@@ -52,6 +52,7 @@ class _SynthModifier(_schema.PropertyModifier, _Namespace):
|
||||
qltest = _Namespace()
|
||||
ql = _Namespace()
|
||||
cpp = _Namespace()
|
||||
rust = _Namespace()
|
||||
synth = _SynthModifier()
|
||||
|
||||
|
||||
@@ -156,6 +157,14 @@ _Pragma("ql_internal")
|
||||
|
||||
_Pragma("cpp_skip")
|
||||
|
||||
_Pragma("rust_skip_doc_test")
|
||||
|
||||
rust.doc_test_function = lambda name, *, lifetimes=(), return_type="()", **kwargs: _annotate(
|
||||
rust_doc_test_function=_schema.FunctionInfo(name,
|
||||
params={f"'{lifetime}": "" for lifetime in lifetimes} | kwargs,
|
||||
return_type=return_type)
|
||||
)
|
||||
|
||||
|
||||
def group(name: str = "") -> _ClassDecorator:
|
||||
return _annotate(group=name)
|
||||
|
||||
@@ -56,6 +56,7 @@ def _get_class(cls: type) -> schema.Class:
|
||||
],
|
||||
doc=schema.split_doc(cls.__doc__),
|
||||
default_doc_name=cls.__dict__.get("_doc_name"),
|
||||
rust_doc_test_function=cls.__dict__.get("_rust_doc_test_function")
|
||||
)
|
||||
|
||||
|
||||
|
||||
9
misc/codegen/templates/rust_test_code.mustache
Normal file
9
misc/codegen/templates/rust_test_code.mustache
Normal file
@@ -0,0 +1,9 @@
|
||||
// generated by {{generator}}
|
||||
|
||||
{{#function}}
|
||||
fn {{name}}<{{#generic_params}}{{^first}}, {{/first}}{{name}}{{#type}}: {{.}}{{/type}}{{/generic_params}}>({{#params}}{{^first}}, {{/first}}{{name}}: {{type}}{{/params}}) -> {{return_type}} {
|
||||
{{/function}}
|
||||
{{code}}
|
||||
{{#function}}
|
||||
}
|
||||
{{/function}}
|
||||
12
rust/.generated.list
generated
12
rust/.generated.list
generated
@@ -1,33 +1,31 @@
|
||||
extractor/src/generated/mod.rs 7cdfedcd68cf8e41134daf810c1af78624082b0c3e8be6570339b1a69a5d457e 7cdfedcd68cf8e41134daf810c1af78624082b0c3e8be6570339b1a69a5d457e
|
||||
extractor/src/generated/top.rs 6a38e468c94037d0c00a1a463753de206b6c8a3ca16f11ee86b4165cd7c91645 6a38e468c94037d0c00a1a463753de206b6c8a3ca16f11ee86b4165cd7c91645
|
||||
ql/lib/codeql/rust/elements/DbFile.qll 056d363e1ba5ec08cacb2e90b8a7a3b47f52ded5dc2289edd4e85921fc50f37e 18e6926f77265a3a6319ca2f3bf3d529d17d46cebdd2ef6753357fdc53c22c70
|
||||
ql/lib/codeql/rust/elements/DbFileConstructor.qll ea93dc49b23b1c6d800ab9d0b9cacfa9dc661bfdb04b9e6efcad2bdb050fb0ab f7a891b1786604eee57a784733555b677e2580770d51d18073b59e7ca65df1d4
|
||||
ql/lib/codeql/rust/elements/DbLocation.qll 1f694594e8e4ab65a8781cd443ad4f864447ca88e2cb65504aee5a779393c84d 003ec72275406eb8f5ddd6ccc2b258fb7c906d4bb2c0ef1ba235f291624321ca
|
||||
ql/lib/codeql/rust/elements/DbLocationConstructor.qll 8848abace985818a5d3a6eddfc4cb200795970146d282b037b4f22ae6230b894 44dba880e17bb1072fa12451ccaae4830fd04dcc61f7403d35510309fde6906e
|
||||
ql/lib/codeql/rust/elements/Declaration.qll d4ec5c83728f1837243caf2f27d06fd05ecdd2ca440112accff99bfd37b45e5f c1cd9b297be8b69207e75d24b29949b9f71c78406ee0ffd38d0b0810288d6140
|
||||
ql/lib/codeql/rust/elements/Function.qll 220eb1d0e6b49e83b7674a9f505d3f529cf7f4d022ddca44fa6367e0d75daa0f d156cff59ecdcffc0d62041b801025b1aaedbc92d44efd107f93f6fd06c34a6d
|
||||
ql/lib/codeql/rust/elements/FunctionConstructor.qll a9269b37182c0bf432f9b2b015691da5dbd64819b9bd25445af229d873014a91 69107a7503af14a51e091e6918094a4e9fc316a72de2e1514f001872ce0f2c0c
|
||||
ql/lib/codeql/rust/elements/Locatable.qll dfc0235cf5aff0ec91d85375ac03998b0e6a69f3722b099330ab0a2161af988a bb1055f59ef7e95e89748765c79f1b5832aa18226f227e689a6801adfc6247ad
|
||||
ql/lib/codeql/rust/elements/Location.qll 17a222ffe30ecfa252bfd2a5d6ef668f9579824b78d241d576c8c0112a9f93f0 9ae822cd9ce3c70824cccae500651f0cba70ad9c9195b611e7542cb928093b0b
|
||||
ql/lib/codeql/rust/elements/Module.qll d8995b361cc672f86a314bd53bd3e4d1ddb26b6afde62eb7c380923810785af0 3c10180c812d89a8116ac6e32cbd4d7ac2f549c8a76d327ed75c764b09251d52
|
||||
ql/lib/codeql/rust/elements/ModuleConstructor.qll 109ed8c1b5c61cc1d3e8613aa8bb8c168dc1943c93b5b622fa79665751b78318 601526c7f56578883d261d14653fdad08329f80fea71de14a5ac5ce671a8d436
|
||||
ql/lib/codeql/rust/elements/UnknownFile.qll 638ac1c5baef4ab8eb98ef4a37202334290001ca183dab769f729b61f9fc0aa9 fae24f8b29c3e5a124e6c71c9bcb0e2bf4bb033eaf3348fd2db3644ce2803b43
|
||||
ql/lib/codeql/rust/elements/UnknownLocation.qll eaadf1702e2f5df0c0917dd9e452a3ceb81e5c2d182675c32e988d826ac3fc71 9bf63fbd74c6114678189a62f63795156c0e5b9ad467c020f16842038e84a226
|
||||
ql/lib/codeql/rust/elements.qll 658d3d26ac2685a077714d41d83ac47f87b0df1c4f0cc7d099c96e06bd1f9d0e 658d3d26ac2685a077714d41d83ac47f87b0df1c4f0cc7d099c96e06bd1f9d0e
|
||||
ql/lib/codeql/rust/generated/DbFile.qll 4dbf1931124291e0d6a958ae882f8aeef006642f72adc7ff86cffd3a4e9a970a 4dbf1931124291e0d6a958ae882f8aeef006642f72adc7ff86cffd3a4e9a970a
|
||||
ql/lib/codeql/rust/generated/DbLocation.qll 735d9351b5eb46a3231b528600dddec3a4122c18c210d4d632a8d4ceaf7f02e9 735d9351b5eb46a3231b528600dddec3a4122c18c210d4d632a8d4ceaf7f02e9
|
||||
ql/lib/codeql/rust/generated/Declaration.qll 4487ac3f5ffa5b92e8628bc04b51e818d4ea1c9a333375cf1b729428d36a4ee7 6481d5e2d99a548f857213a283da75d45db8b3adac949e90fd5d17ceb5e22b54
|
||||
ql/lib/codeql/rust/generated/Element.qll 21567fa7348dccdf69dd34e73cb6de7cc9c7e0f3f7bb419a1abd787f7dc851a1 21567fa7348dccdf69dd34e73cb6de7cc9c7e0f3f7bb419a1abd787f7dc851a1
|
||||
ql/lib/codeql/rust/generated/File.qll 2eff5c882d044d2e360fe6382fb55e5a45f6ccb9df323cfa1fae41eae9d2a47f 87e7a906b3a1b4de056952e288ddd7f69fa7cb1bd9dc7dd3972868a9002ac1e4
|
||||
ql/lib/codeql/rust/generated/Function.qll 6429619a284cadaf64d74ab408f57a399c7e5df2ad182bd38f77b580879d9e33 8c4cfa4f23b5ed461f0f8aa40c5833a953fc9ba3f99584f0f05cf7d7d6a9b617
|
||||
ql/lib/codeql/rust/generated/Function.qll e41ca13aadd457a4fd853ac4e2f643de199e2b4d0a320add0cab890a9b72844a fc27a68775957e537eb95951cb7109e174b8dc5b0b5e0d8cc24901d431faad2f
|
||||
ql/lib/codeql/rust/generated/Locatable.qll 9e9685bba50ad2220701f3465e63af9331f7f9dc548ad906ff954fc2ce0a4400 78c89b2cc78a357d682ab65310dd474603071f07c1eaaab07711714ce17549f2
|
||||
ql/lib/codeql/rust/generated/Location.qll bce4c72988ec6fedd1439c60a37c45aa6147c962904709ef9f12206937174be4 d57000571771a2d997c50d9a43ef1c2f075960f847effa0e80ea91fd4c6b4d6c
|
||||
ql/lib/codeql/rust/generated/Module.qll 2a931a4f2cdb2fee00ed83af045ea63d36b7dbd708e58c30445b5610feaae333 cd62add5c31a509f965aa294f44a1607ec7c62e3a9e3fe9ee063b3c814f4eb62
|
||||
ql/lib/codeql/rust/generated/ParentChild.qll b44f149bff05a96ee16c88883f06d5d2c159a89423ec32b00765da6964af029e 1d13e54fbc27d9cc29405a21c2f4a63043cbb7aade317184f440a17d3f5645c4
|
||||
ql/lib/codeql/rust/generated/PureSynthConstructors.qll 5eb1fc4f6a04172c34ae31e4931e4bf1f8b72fbe414c5f644731a45372d13573 5eb1fc4f6a04172c34ae31e4931e4bf1f8b72fbe414c5f644731a45372d13573
|
||||
ql/lib/codeql/rust/generated/Raw.qll 921cb1afb5c1c3177acb557151755d4f97e7c65f656c5069d6f095b0e078074f a25fdad01e70bbab2d2663b152a4a5844677edcf0a0af2ec93c42dc3248ac9b2
|
||||
ql/lib/codeql/rust/generated/Raw.qll 8d6d9e0cf2c9a8a82f9238e63904e9d19e4ae040d614fbfcab8c01c814576f2a 54c3f382587317b336fb76f496e566fd654008f3394271c695ae9a5605675c38
|
||||
ql/lib/codeql/rust/generated/Synth.qll d278de9c2d06cb7549cd8f2e10ed186827a2ceab6ff46725ca76e78e7fecac72 acacd9afc5ca4a288e037a43375d933c3ba3cd8d08ef122b31695e74be260eb2
|
||||
ql/lib/codeql/rust/generated/SynthConstructors.qll 35b36df0c4fff05bcbd4ed10b1e6fa2e58fe8d8c818e7805111044825788fc01 35b36df0c4fff05bcbd4ed10b1e6fa2e58fe8d8c818e7805111044825788fc01
|
||||
ql/lib/codeql/rust/generated/UnknownFile.qll ec9d1a3f15ecbf1743d4e39cb3b2f217aa9b54951c93302c2c4c238c3f0ce595 ec9d1a3f15ecbf1743d4e39cb3b2f217aa9b54951c93302c2c4c238c3f0ce595
|
||||
ql/lib/codeql/rust/generated/UnknownLocation.qll a19e2838c52d702d268ae530f3dbd6fcd8bb28a237a52636a960f225454103cf a19e2838c52d702d268ae530f3dbd6fcd8bb28a237a52636a960f225454103cf
|
||||
ql/test/extractor-tests/generated/File/File.ql dec43be882fad904fab0c6447ca93633d801cb08ff8bec309befde7d2b9e5dda 74e1f1d698558c35fa03935cc34f4c8145d376b56d7657b18aeb338f5ca752cf
|
||||
ql/test/extractor-tests/generated/Function/Function.ql ae5d44a85047d50d8fbd3b62290c6935f061f07076b0070998173957e54eb43f 3e7fb6fb82463b96577394213915d8deae5332acdec2fcc07aa3eb8560420edd
|
||||
ql/test/extractor-tests/generated/Function/gen_function.rs d5c3cced4c377b05a4aa7e7b82deeb0f4c0bdf5dbca19490c589040ef79c9314 d5c3cced4c377b05a4aa7e7b82deeb0f4c0bdf5dbca19490c589040ef79c9314
|
||||
ql/test/extractor-tests/generated/Module/MISSING_SOURCE.txt cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e
|
||||
|
||||
8
rust/.gitattributes
generated
vendored
8
rust/.gitattributes
generated
vendored
@@ -1,18 +1,15 @@
|
||||
/.generated.list linguist-generated
|
||||
/.gitattributes linguist-generated
|
||||
/extractor/src/generated/mod.rs linguist-generated
|
||||
/extractor/src/generated/top.rs linguist-generated
|
||||
/ql/lib/codeql/rust/elements/DbFile.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/DbFileConstructor.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/DbLocation.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/DbLocationConstructor.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Declaration.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Function.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/FunctionConstructor.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Locatable.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Location.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Module.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/ModuleConstructor.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/UnknownFile.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/UnknownLocation.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements.qll linguist-generated
|
||||
/ql/lib/codeql/rust/generated/DbFile.qll linguist-generated
|
||||
/ql/lib/codeql/rust/generated/DbLocation.qll linguist-generated
|
||||
@@ -32,4 +29,5 @@
|
||||
/ql/lib/codeql/rust/generated/UnknownLocation.qll linguist-generated
|
||||
/ql/test/extractor-tests/generated/File/File.ql linguist-generated
|
||||
/ql/test/extractor-tests/generated/Function/Function.ql linguist-generated
|
||||
/ql/test/extractor-tests/generated/Function/gen_function.rs linguist-generated
|
||||
/ql/test/extractor-tests/generated/Module/MISSING_SOURCE.txt linguist-generated
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# configuration file for Swift code generation default options
|
||||
--generate=dbscheme,ql,rust
|
||||
--generate=dbscheme,rusttest,ql,rust
|
||||
--dbscheme=ql/lib/rust.dbscheme
|
||||
--ql-output=ql/lib/codeql/rust/generated
|
||||
--ql-stub-output=ql/lib/codeql/rust/elements
|
||||
|
||||
@@ -4,6 +4,20 @@
|
||||
|
||||
private import codeql.rust.generated.Function
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A function declaration. For example
|
||||
* ```
|
||||
* fn foo(x: u32) -> u64 { (x + 1).into()
|
||||
* }
|
||||
* ```
|
||||
* A function declaration within a trait might not have a body:
|
||||
* ```
|
||||
* trait Trait {
|
||||
* fn bar();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Function extends Generated::Function {
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
11
rust/ql/lib/codeql/rust/generated/Function.qll
generated
11
rust/ql/lib/codeql/rust/generated/Function.qll
generated
@@ -14,6 +14,17 @@ import codeql.rust.elements.Declaration
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* A function declaration. For example
|
||||
* ```
|
||||
* fn foo(x: u32) -> u64 { (x + 1).into()
|
||||
* }
|
||||
* ```
|
||||
* A function declaration within a trait might not have a body:
|
||||
* ```
|
||||
* trait Trait {
|
||||
* fn bar();
|
||||
* }
|
||||
* ```
|
||||
* INTERNAL: Do not reference the `Generated::Function` class directly.
|
||||
* Use the subclass `Function`, where the following predicates are available.
|
||||
*/
|
||||
|
||||
11
rust/ql/lib/codeql/rust/generated/Raw.qll
generated
11
rust/ql/lib/codeql/rust/generated/Raw.qll
generated
@@ -81,6 +81,17 @@ module Raw {
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A function declaration. For example
|
||||
* ```
|
||||
* fn foo(x: u32) -> u64 { (x + 1).into()
|
||||
* }
|
||||
* ```
|
||||
* A function declaration within a trait might not have a body:
|
||||
* ```
|
||||
* trait Trait {
|
||||
* fn bar();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Function extends @function, Declaration {
|
||||
override string toString() { result = "Function" }
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
| test.rs:0:0:0:11 | foo | getName: | foo |
|
||||
| test.rs:1:0:1:11 | bar | getName: | bar |
|
||||
| test.rs:2:0:2:11 | baz | getName: | baz |
|
||||
| gen_function.rs:2:0:3:40 | foo | getName: | foo |
|
||||
|
||||
11
rust/ql/test/extractor-tests/generated/Function/function.rs
Normal file
11
rust/ql/test/extractor-tests/generated/Function/function.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
// generated by codegen
|
||||
|
||||
fn my_test<'a, 'b, T: Eq>(x: &'a [T], y: &'b [T]) -> &'a [T] {
|
||||
// A function declaration. For example
|
||||
fn foo(x: u32) -> u64 { (x + 1).into()
|
||||
}
|
||||
// A function declaration within a trait might not have a body:
|
||||
trait Trait {
|
||||
fn bar();
|
||||
}
|
||||
}
|
||||
11
rust/ql/test/extractor-tests/generated/Function/gen_function.rs
generated
Normal file
11
rust/ql/test/extractor-tests/generated/Function/gen_function.rs
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
// generated by codegen
|
||||
|
||||
fn my_test<'a, 'b, T: Eq>(x: &'a [T], y: &'b [T]) -> &'a [T] {
|
||||
// A function declaration. For example
|
||||
fn foo(x: u32) -> u64 { (x + 1).into()
|
||||
}
|
||||
// A function declaration within a trait might not have a body:
|
||||
trait Trait {
|
||||
fn bar();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fn foo() {}
|
||||
fn bar() {}
|
||||
fn baz() {}
|
||||
@@ -56,5 +56,19 @@ class Module(Declaration):
|
||||
# TODO name
|
||||
declarations: list[Declaration] | child
|
||||
|
||||
@rust.doc_test_function("my_test", lifetimes="ab", T="Eq", x="&'a [T]", y="&'b [T]", return_type="&'a [T]")
|
||||
class Function(Declaration):
|
||||
"""
|
||||
A function declaration. For example
|
||||
```
|
||||
fn foo(x: u32) -> u64 { (x + 1).into()
|
||||
}
|
||||
```
|
||||
A function declaration within a trait might not have a body:
|
||||
```
|
||||
trait Trait {
|
||||
fn bar();
|
||||
}
|
||||
```
|
||||
"""
|
||||
name: string
|
||||
|
||||
Reference in New Issue
Block a user