Extract runnables
This commit is contained in:
parent
e847a1b7a6
commit
36bd28633b
@ -26,6 +26,18 @@ pub struct Symbol {
|
||||
pub range: TextRange,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Runnable {
|
||||
pub range: TextRange,
|
||||
pub kind: RunnableKind,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RunnableKind {
|
||||
Test { name: String },
|
||||
Bin,
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn new(text: &str) -> File {
|
||||
File {
|
||||
@ -78,6 +90,28 @@ impl File {
|
||||
let syntax = self.inner.syntax();
|
||||
extend_selection::extend_selection(syntax.as_ref(), range)
|
||||
}
|
||||
|
||||
pub fn runnables(&self) -> Vec<Runnable> {
|
||||
self.inner
|
||||
.functions()
|
||||
.filter_map(|f| {
|
||||
let name = f.name()?.text();
|
||||
let kind = if name == "main" {
|
||||
RunnableKind::Bin
|
||||
} else if f.has_atom_attr("test") {
|
||||
RunnableKind::Test {
|
||||
name: name.to_string()
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
Some(Runnable {
|
||||
range: f.syntax().range(),
|
||||
kind,
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,11 +37,33 @@ fn main() {}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_runnables() {
|
||||
let file = file(r#"
|
||||
fn main() {}
|
||||
|
||||
#[test]
|
||||
fn test_foo() {}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_foo() {}
|
||||
"#);
|
||||
let runnables = file.runnables();
|
||||
dbg_eq(
|
||||
&runnables,
|
||||
r#"[Runnable { range: [1; 13), kind: Bin },
|
||||
Runnable { range: [15; 39), kind: Test { name: "test_foo" } },
|
||||
Runnable { range: [41; 75), kind: Test { name: "test_foo" } }]"#,
|
||||
)
|
||||
}
|
||||
|
||||
fn file(text: &str) -> File {
|
||||
File::new(text)
|
||||
}
|
||||
|
||||
fn dbg_eq(actual: &impl fmt::Debug, expected: &str) {
|
||||
let actual = format!("{:?}", actual);
|
||||
let expected = expected.lines().map(|l| l.trim()).join(" ");
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
75
src/ast.rs
75
src/ast.rs
@ -1,11 +1,25 @@
|
||||
use std::sync::Arc;
|
||||
use {SyntaxNode, SyntaxRoot, TreeRoot};
|
||||
use {
|
||||
SyntaxNode, SyntaxRoot, TreeRoot,
|
||||
SyntaxKind::*,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct File<R: TreeRoot = Arc<SyntaxRoot>> {
|
||||
syntax: SyntaxNode<R>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Function<R: TreeRoot = Arc<SyntaxRoot>> {
|
||||
syntax: SyntaxNode<R>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Name<R: TreeRoot = Arc<SyntaxRoot>> {
|
||||
syntax: SyntaxNode<R>,
|
||||
}
|
||||
|
||||
|
||||
impl File<Arc<SyntaxRoot>> {
|
||||
pub fn parse(text: &str) -> Self {
|
||||
File {
|
||||
@ -14,6 +28,65 @@ impl File<Arc<SyntaxRoot>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: TreeRoot> File<R> {
|
||||
pub fn functions<'a>(&'a self) -> impl Iterator<Item = Function<R>> + 'a {
|
||||
self.syntax
|
||||
.children()
|
||||
.filter(|node| node.kind() == FN_ITEM)
|
||||
.map(|node| Function { syntax: node })
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: TreeRoot> Function<R> {
|
||||
pub fn syntax(&self) -> SyntaxNode<R> {
|
||||
self.syntax.clone()
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<Name<R>> {
|
||||
self.syntax
|
||||
.children()
|
||||
.filter(|node| node.kind() == NAME)
|
||||
.map(|node| Name { syntax: node })
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn has_atom_attr(&self, atom: &str) -> bool {
|
||||
self.syntax
|
||||
.children()
|
||||
.filter(|node| node.kind() == ATTR)
|
||||
.any(|attr| {
|
||||
let mut metas = attr.children().filter(|node| node.kind() == META_ITEM);
|
||||
let meta = match metas.next() {
|
||||
None => return false,
|
||||
Some(meta) => {
|
||||
if metas.next().is_some() {
|
||||
return false;
|
||||
}
|
||||
meta
|
||||
}
|
||||
};
|
||||
let mut children = meta.children();
|
||||
match children.next() {
|
||||
None => false,
|
||||
Some(child) => {
|
||||
if children.next().is_some() {
|
||||
return false;
|
||||
}
|
||||
child.kind() == IDENT && child.text() == atom
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: TreeRoot> Name<R> {
|
||||
pub fn text(&self) -> String {
|
||||
self.syntax.text()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<R: TreeRoot> File<R> {
|
||||
pub fn syntax(&self) -> SyntaxNode<R> {
|
||||
self.syntax.clone()
|
||||
|
Loading…
x
Reference in New Issue
Block a user