Skip to content
This repository was archived by the owner on Oct 31, 2023. It is now read-only.

Commit 524fe38

Browse files
authored
Release 0.2.2 (#22)
* list all functions in a Rust project - Remove support for detecting `#[autometrics]` annotation on struct statements, as it is not supported in Rust, and simplifies the code * doc: update changelog * nit: format, lint * chore: Release am_list version 0.2.2
1 parent 80a5ac8 commit 524fe38

13 files changed

+413
-188
lines changed

CHANGELOG.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
## [Unreleased] - ReleaseDate
1111

12+
## [Version 0.2.2] - 2023-06-19
13+
14+
### Added
15+
16+
- [Rust] The `list` subcommand now takes an optional `--all-functions` (short `-a`) flag,
17+
which lists all functions/methods in the project instead of only the ones with the
18+
autometrics annotation. This allows to get an overview of how many functions are
19+
autometricized. The flag will crash on non-Rust implementations for now.
20+
1221
## [Version 0.2.1] - 2023-06-16
1322

1423
### Fixed
@@ -53,7 +62,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5362
### Security
5463

5564
<!-- next-url -->
56-
[Unreleased]: https://github.com/gagbo/am_list/compare/v0.2.1...HEAD
65+
[Unreleased]: https://github.com/autometrics-dev/am_list/compare/v0.2.2...HEAD
66+
[Version 0.2.2]: https://github.com/gagbo/am_list/compare/v0.2.1...v0.2.2
5767
[Version 0.2.1]: https://github.com/gagbo/am_list/compare/v0.2.0...v0.2.1
5868
[Version 0.2.0]: https://github.com/gagbo/am_list/compare/v0.1.0...v0.2.0
5969
[Version 0.1.0]: https://github.com/gagbo/am_list/releases/tag/v0.1.0

CONTRIBUTING.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@
44

55
The complete release cycle is handled and automated by the combination of `cargo-dist` and `cargo-release`.
66

7-
When ready for a release, using `cargo release --(patch|minor|major)` should be enough.
7+
When ready for a release, using `cargo release --(patch|minor)` or `cargo release NEW_MAJOR` should be enough.
8+
9+
### Prerequisites
10+
11+
Only `cargo-release` is needed to create a new release:
12+
```console
13+
$ cargo install --locked cargo-release
14+
```
15+
16+
Also, you need to have the authorization to both:
17+
- create and push tags on `release/*` branches in the Github repo
18+
- create and push crates on `crates-io` registry for [`am_list` crate](https://crates.io/crates/am_list)
819

920
### Release a breaking `0.Y` version
1021

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[package]
22
name = "am_list"
3-
version = "0.2.1"
3+
version = "0.2.2"
44
edition = "2021"
5-
repository = "https://github.com/gagbo/am_list"
6-
authors = ["Gerry Agbobada <[email protected]>"]
5+
repository = "https://github.com/autometrics-dev/am_list"
6+
authors = ["Fiberplane <[email protected]>", "Gerry Agbobada <[email protected]>"]
77
description = "A tree-sitter-powered command line tool to list functions marked with Autometrics annotations"
88
homepage = "https://autometrics.dev"
99
license = "MIT"

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Use the installer script to pull the latest version directly from Github
1616
(change `VERSION` accordingly):
1717

1818
```console
19-
VERSION=0.2.0 curl --proto '=https' --tlsv1.2 -LsSf https://github.com/gagbo/am_list/releases/download/v$VERSION/am_list-installer.sh | sh
19+
VERSION=0.2.0 curl --proto '=https' --tlsv1.2 -LsSf https://github.com/autometrics-dev/am_list/releases/download/v$VERSION/am_list-installer.sh | sh
2020
```
2121

2222
And run the binary

release.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ pre-release-replacements = [
33
{file="CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1},
44
{file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}"},
55
{file="CHANGELOG.md", search="<!-- next-header -->", replace="<!-- next-header -->\n\n## [Unreleased] - ReleaseDate", exactly=1},
6-
{file="CHANGELOG.md", search="<!-- next-url -->", replace="<!-- next-url -->\n[Unreleased]: https://github.com/gagbo/am_list/compare/{{tag_name}}...HEAD", exactly=1},
6+
{file="CHANGELOG.md", search="<!-- next-url -->", replace="<!-- next-url -->\n[Unreleased]: https://github.com/autometrics-dev/am_list/compare/{{tag_name}}...HEAD", exactly=1},
77
]
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
((function_item
2+
name: (identifier) @func.name))
3+
4+
;; It is impossible to do arbitrary levels of nesting, so we just detect module declarations to
5+
;; call this query recursively on the declaration_list of the module.
6+
;; Ref: https://github.com/tree-sitter/tree-sitter/discussions/981
7+
((mod_item
8+
name: (identifier) @mod.name
9+
body: (declaration_list) @mod.contents))
10+
11+
;; We want to skip the "bare" function detection (@func.name pattern in this file) when function
12+
;; is within an impl block. The reason is that we cannot properly report the module name (which should
13+
;; be the struct type name) if we use this detection method.
14+
;; Therefore, we skip bare functions that are detected within impl blocks, and instead rely on
15+
;; recursion to find functions within impl blocks.
16+
;;
17+
;; We also consider that an "impl block" is an "in-file" module for the purpose of recursion
18+
;; This allows to detect functions that have the autometrics annotation within an impl block,
19+
;; _while allowing to skip functions in impl blocks detected by the main query_.
20+
((impl_item
21+
type: (type_identifier) @impl.type
22+
body: (declaration_list) @impl.contents))

runtime/queries/rust/autometrics.scm

+14-58
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
name: (identifier) @func.name)
1111
(#eq? @attr "autometrics"))
1212

13-
1413
((attribute_item)*
1514
.
1615
(attribute_item
@@ -19,67 +18,11 @@
1918
.
2019
(attribute_item)*
2120
.
22-
(struct_item
23-
name: (type_identifier) @type.target)
24-
2521
(impl_item
2622
type: (type_identifier) @type.impl
2723
body: (declaration_list
2824
(function_item
29-
name: (identifier) @func.name)))
30-
31-
(#eq? @attr "autometrics")
32-
(#eq? @type.impl @type.target))
33-
34-
35-
((impl_item
36-
type: (type_identifier) @type.impl
37-
body: (declaration_list
38-
(function_item
39-
name: (identifier) @func.name)))
40-
41-
(attribute_item)*
42-
.
43-
(attribute_item
44-
(attribute
45-
(identifier) @attr))
46-
.
47-
(attribute_item)*
48-
.
49-
(struct_item
50-
name: (type_identifier) @type.target)
51-
52-
(#eq? @attr "autometrics")
53-
(#eq? @type.impl @type.target))
54-
55-
56-
((attribute_item)*
57-
.
58-
(attribute_item
59-
(attribute
60-
(identifier) @attr))
61-
.
62-
(attribute_item)*
63-
.
64-
(struct_item
65-
name: (type_identifier) @type.target)
66-
67-
(#eq? @attr "autometrics"))
68-
69-
70-
((attribute_item)*
71-
.
72-
(attribute_item
73-
(attribute
74-
(identifier) @attr))
75-
.
76-
(attribute_item)*
77-
.
78-
(impl_item
79-
type: (type_identifier) @type.impl
80-
body: (declaration_list
81-
(function_item
82-
name: (identifier) @func.name)))
25+
name: (identifier) @inner.func.name)))
8326

8427
(#eq? @attr "autometrics"))
8528

@@ -89,3 +32,16 @@
8932
((mod_item
9033
name: (identifier) @mod.name
9134
body: (declaration_list) @mod.contents))
35+
36+
;; We want to skip the "bare" function detection (@func.name pattern in this file) when function
37+
;; is within an impl block. The reason is that we cannot properly report the module name (which should
38+
;; be the struct type name) if we use this detection method.
39+
;; Therefore, we skip bare functions that are detected within impl blocks, and instead rely on
40+
;; recursion to find functions within impl blocks.
41+
;;
42+
;; We also consider that an "impl block" is an "in-file" module for the purpose of recursion
43+
;; This allows to detect functions that have the autometrics annotation within an impl block,
44+
;; _while allowing to skip functions in impl blocks detected by the main query_.
45+
((impl_item
46+
type: (type_identifier) @impl.type
47+
body: (declaration_list) @impl.contents))

src/go.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ impl ListAmFunctions for Impl {
6868
result.extend(list.into_iter().flatten());
6969
Ok(result)
7070
}
71+
72+
fn list_all_functions(&mut self, _project_root: &Path) -> Result<Vec<ExpectedAmLabel>> {
73+
unimplemented!("listing all functions in Golang")
74+
}
7175
}
7276

7377
fn new_parser() -> Result<Parser> {
@@ -83,10 +87,10 @@ fn query_builder() -> Result<(Query, u32, u32)> {
8387
)?;
8488
let idx = query
8589
.capture_index_for_name(FUNC_NAME_CAPTURE)
86-
.ok_or(AmlError::MissingFuncNameCapture)?;
90+
.ok_or_else(|| AmlError::MissingFuncNameCapture(FUNC_NAME_CAPTURE.into()))?;
8791
let mod_idx = query
8892
.capture_index_for_name(PACK_NAME_CAPTURE)
89-
.ok_or(AmlError::MissingFuncNameCapture)?;
93+
.ok_or_else(|| AmlError::MissingFuncNameCapture(PACK_NAME_CAPTURE.into()))?;
9094
Ok((query, idx, mod_idx))
9195
}
9296

src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ impl Display for ExpectedAmLabel {
2323

2424
pub trait ListAmFunctions {
2525
fn list_autometrics_functions(&mut self, project_root: &Path) -> Result<Vec<ExpectedAmLabel>>;
26+
fn list_all_functions(&mut self, project_root: &Path) -> Result<Vec<ExpectedAmLabel>>;
2627
}
2728

2829
pub type Result<T> = std::result::Result<T, AmlError>;
@@ -33,8 +34,8 @@ pub enum AmlError {
3334
CreateParser(#[from] LanguageError),
3435
#[error("Issue creating the TreeSitter query")]
3536
CreateQuery(#[from] QueryError),
36-
#[error("The query is missing a function name capture")]
37-
MissingFuncNameCapture,
37+
#[error("The query is missing a function name capture: {0}")]
38+
MissingFuncNameCapture(String),
3839
#[error("Parsing error")]
3940
Parsing,
4041
#[error("Invalid text in source")]

src/main.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ struct ListArgs {
2929
/// - For Go projects it must be the root of the repository.
3030
#[arg(value_name = "ROOT")]
3131
root: PathBuf,
32+
/// List all functions instead of only the autometricized ones (defaults to false)
33+
#[arg(short, long, default_value = "false")]
34+
all_functions: bool,
3235
/// Pretty print the resulting JSON (defaults to false)
3336
#[arg(short, long, default_value = "false")]
3437
pretty: bool,
@@ -68,15 +71,15 @@ fn main() -> anyhow::Result<()> {
6871
let root = args.root;
6972
info!("Autometrics functions in {}:", root.display());
7073

71-
let mut res = match args.language {
72-
Language::Rust => {
73-
let mut implementor = am_list::rust::Impl {};
74-
implementor.list_autometrics_functions(&root)?
75-
}
76-
Language::Go => {
77-
let mut implementor = am_list::go::Impl {};
78-
implementor.list_autometrics_functions(&root)?
79-
}
74+
let mut implementor: Box<dyn ListAmFunctions> = match args.language {
75+
Language::Rust => Box::new(am_list::rust::Impl {}),
76+
Language::Go => Box::new(am_list::go::Impl {}),
77+
};
78+
79+
let mut res = if args.all_functions {
80+
implementor.list_all_functions(&root)?
81+
} else {
82+
implementor.list_autometrics_functions(&root)?
8083
};
8184

8285
res.sort();

0 commit comments

Comments
 (0)