This commit is contained in:
Aleksey Kladov 2018-08-16 12:51:40 +03:00
parent 1193c5f829
commit 7094291573
18 changed files with 260 additions and 276 deletions

View file

@ -26,9 +26,8 @@ use std::{
use libsyntax2::{ use libsyntax2::{
TextUnit, TextUnit,
ast::{self, AstNode}, ast::{self, AstNode},
algo::{find_leaf_at_offset, ancestors},
}; };
use libeditor::{LineIndex, FileSymbol}; use libeditor::{LineIndex, FileSymbol, find_node};
use self::symbol_index::FileSymbols; use self::symbol_index::FileSymbols;
pub use self::symbol_index::Query; pub use self::symbol_index::Query;
@ -123,13 +122,7 @@ impl World {
let file = self.file_syntax(id)?; let file = self.file_syntax(id)?;
let syntax = file.syntax(); let syntax = file.syntax();
let syntax = syntax.as_ref(); let syntax = syntax.as_ref();
let name_ref = let name_ref = find_node::<ast::NameRef<_>>(syntax, offset);
find_leaf_at_offset(syntax, offset)
.left_biased()
.into_iter()
.flat_map(|node| ancestors(node))
.flat_map(ast::NameRef::cast)
.next();
let name = match name_ref { let name = match name_ref {
None => return Ok(vec![]), None => return Ok(vec![]),
Some(name_ref) => name_ref.text(), Some(name_ref) => name_ref.text(),

View file

@ -66,7 +66,7 @@ fn find_non_trivia_leaf(syntax: SyntaxNodeRef, offset: TextUnit) -> Option<Synta
.find(|leaf| !leaf.kind().is_trivia()) .find(|leaf| !leaf.kind().is_trivia())
} }
fn find_node<'a, N: AstNode<&'a SyntaxRoot>>(syntax: SyntaxNodeRef<'a>, offset: TextUnit) -> Option<N> { pub fn find_node<'a, N: AstNode<&'a SyntaxRoot>>(syntax: SyntaxNodeRef<'a>, offset: TextUnit) -> Option<N> {
let leaf = find_non_trivia_leaf(syntax, offset)?; let leaf = find_non_trivia_leaf(syntax, offset)?;
ancestors(leaf) ancestors(leaf)
.filter_map(N::cast) .filter_map(N::cast)

View file

@ -21,7 +21,10 @@ pub use self::{
extend_selection::extend_selection, extend_selection::extend_selection,
symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, symbols::{StructureNode, file_structure, FileSymbol, file_symbols},
edit::{EditBuilder, Edit, AtomEdit}, edit::{EditBuilder, Edit, AtomEdit},
code_actions::{flip_comma, add_derive, ActionResult, CursorPosition}, code_actions::{
ActionResult, CursorPosition, find_node,
flip_comma, add_derive,
},
}; };
#[derive(Debug)] #[derive(Debug)]
@ -59,9 +62,7 @@ pub fn matching_brace(file: &ast::File, offset: TextUnit) -> Option<TextUnit> {
L_PAREN, R_PAREN, L_PAREN, R_PAREN,
L_ANGLE, R_ANGLE, L_ANGLE, R_ANGLE,
]; ];
let syntax = file.syntax(); let (brace_node, brace_idx) = find_leaf_at_offset(file.syntax_ref(), offset)
let syntax = syntax.as_ref();
let (brace_node, brace_idx) = find_leaf_at_offset(syntax, offset)
.filter_map(|node| { .filter_map(|node| {
let idx = BRACES.iter().position(|&brace| brace == node.kind())?; let idx = BRACES.iter().position(|&brace| brace == node.kind())?;
Some((node, idx)) Some((node, idx))
@ -75,9 +76,8 @@ pub fn matching_brace(file: &ast::File, offset: TextUnit) -> Option<TextUnit> {
} }
pub fn highlight(file: &ast::File) -> Vec<HighlightedRange> { pub fn highlight(file: &ast::File) -> Vec<HighlightedRange> {
let syntax = file.syntax();
let mut res = Vec::new(); let mut res = Vec::new();
for node in walk::preorder(syntax.as_ref()) { for node in walk::preorder(file.syntax_ref()) {
let tag = match node.kind() { let tag = match node.kind() {
ERROR => "error", ERROR => "error",
COMMENT | DOC_COMMENT => "comment", COMMENT | DOC_COMMENT => "comment",
@ -99,10 +99,9 @@ pub fn highlight(file: &ast::File) -> Vec<HighlightedRange> {
} }
pub fn diagnostics(file: &ast::File) -> Vec<Diagnostic> { pub fn diagnostics(file: &ast::File) -> Vec<Diagnostic> {
let syntax = file.syntax();
let mut res = Vec::new(); let mut res = Vec::new();
for node in walk::preorder(syntax.as_ref()) { for node in walk::preorder(file.syntax_ref()) {
if node.kind() == ERROR { if node.kind() == ERROR {
res.push(Diagnostic { res.push(Diagnostic {
range: node.range(), range: node.range(),

View file

@ -26,8 +26,7 @@ pub struct FileSymbol {
} }
pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> { pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> {
let syntax = file.syntax(); preorder(file.syntax_ref())
preorder(syntax.as_ref())
.filter_map(to_symbol) .filter_map(to_symbol)
.collect() .collect()
} }
@ -57,9 +56,8 @@ fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
pub fn file_structure(file: &ast::File) -> Vec<StructureNode> { pub fn file_structure(file: &ast::File) -> Vec<StructureNode> {
let mut res = Vec::new(); let mut res = Vec::new();
let mut stack = Vec::new(); let mut stack = Vec::new();
let syntax = file.syntax();
for event in walk(syntax.as_ref()) { for event in walk(file.syntax_ref()) {
match event { match event {
WalkEvent::Enter(node) => { WalkEvent::Enter(node) => {
match structure_node(node) { match structure_node(node) {

View file

@ -23,6 +23,31 @@ impl<R: TreeRoot> AstNode<R> for ArrayType<R> {
impl<R: TreeRoot> ArrayType<R> {} impl<R: TreeRoot> ArrayType<R> {}
// Attr
#[derive(Debug, Clone, Copy)]
pub struct Attr<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
}
impl<R: TreeRoot> AstNode<R> for Attr<R> {
fn cast(syntax: SyntaxNode<R>) -> Option<Self> {
match syntax.kind() {
ATTR => Some(Attr { syntax }),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> Attr<R> {
pub fn value(&self) -> Option<TokenTree<R>> {
self.syntax()
.children()
.filter_map(TokenTree::cast)
.next()
}
}
// ConstDef // ConstDef
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct ConstDef<R: TreeRoot = Arc<SyntaxRoot>> { pub struct ConstDef<R: TreeRoot = Arc<SyntaxRoot>> {
@ -40,6 +65,7 @@ impl<R: TreeRoot> AstNode<R> for ConstDef<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for ConstDef<R> {} impl<R: TreeRoot> ast::NameOwner<R> for ConstDef<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for ConstDef<R> {}
impl<R: TreeRoot> ConstDef<R> {} impl<R: TreeRoot> ConstDef<R> {}
// DynTraitType // DynTraitType
@ -77,6 +103,7 @@ impl<R: TreeRoot> AstNode<R> for EnumDef<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for EnumDef<R> {} impl<R: TreeRoot> ast::NameOwner<R> for EnumDef<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for EnumDef<R> {}
impl<R: TreeRoot> EnumDef<R> {} impl<R: TreeRoot> EnumDef<R> {}
// File // File
@ -120,6 +147,7 @@ impl<R: TreeRoot> AstNode<R> for FnDef<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for FnDef<R> {} impl<R: TreeRoot> ast::NameOwner<R> for FnDef<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for FnDef<R> {}
impl<R: TreeRoot> FnDef<R> {} impl<R: TreeRoot> FnDef<R> {}
// FnPointerType // FnPointerType
@ -211,6 +239,7 @@ impl<R: TreeRoot> AstNode<R> for Module<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for Module<R> {} impl<R: TreeRoot> ast::NameOwner<R> for Module<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for Module<R> {}
impl<R: TreeRoot> Module<R> {} impl<R: TreeRoot> Module<R> {}
// Name // Name
@ -266,6 +295,7 @@ impl<R: TreeRoot> AstNode<R> for NamedField<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for NamedField<R> {} impl<R: TreeRoot> ast::NameOwner<R> for NamedField<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for NamedField<R> {}
impl<R: TreeRoot> NamedField<R> {} impl<R: TreeRoot> NamedField<R> {}
// NeverType // NeverType
@ -436,6 +466,7 @@ impl<R: TreeRoot> AstNode<R> for StaticDef<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for StaticDef<R> {} impl<R: TreeRoot> ast::NameOwner<R> for StaticDef<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for StaticDef<R> {}
impl<R: TreeRoot> StaticDef<R> {} impl<R: TreeRoot> StaticDef<R> {}
// StructDef // StructDef
@ -455,6 +486,7 @@ impl<R: TreeRoot> AstNode<R> for StructDef<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for StructDef<R> {} impl<R: TreeRoot> ast::NameOwner<R> for StructDef<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for StructDef<R> {}
impl<R: TreeRoot> StructDef<R> { impl<R: TreeRoot> StructDef<R> {
pub fn fields<'a>(&'a self) -> impl Iterator<Item = NamedField<R>> + 'a { pub fn fields<'a>(&'a self) -> impl Iterator<Item = NamedField<R>> + 'a {
self.syntax() self.syntax()
@ -463,6 +495,24 @@ impl<R: TreeRoot> StructDef<R> {
} }
} }
// TokenTree
#[derive(Debug, Clone, Copy)]
pub struct TokenTree<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
}
impl<R: TreeRoot> AstNode<R> for TokenTree<R> {
fn cast(syntax: SyntaxNode<R>) -> Option<Self> {
match syntax.kind() {
TOKEN_TREE => Some(TokenTree { syntax }),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> TokenTree<R> {}
// TraitDef // TraitDef
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct TraitDef<R: TreeRoot = Arc<SyntaxRoot>> { pub struct TraitDef<R: TreeRoot = Arc<SyntaxRoot>> {
@ -480,6 +530,7 @@ impl<R: TreeRoot> AstNode<R> for TraitDef<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for TraitDef<R> {} impl<R: TreeRoot> ast::NameOwner<R> for TraitDef<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for TraitDef<R> {}
impl<R: TreeRoot> TraitDef<R> {} impl<R: TreeRoot> TraitDef<R> {}
// TupleType // TupleType
@ -517,6 +568,7 @@ impl<R: TreeRoot> AstNode<R> for TypeDef<R> {
} }
impl<R: TreeRoot> ast::NameOwner<R> for TypeDef<R> {} impl<R: TreeRoot> ast::NameOwner<R> for TypeDef<R> {}
impl<R: TreeRoot> ast::AttrsOwner<R> for TypeDef<R> {}
impl<R: TreeRoot> TypeDef<R> {} impl<R: TreeRoot> TypeDef<R> {}
// TypeRef // TypeRef

View file

@ -2,10 +2,11 @@ mod generated;
use std::sync::Arc; use std::sync::Arc;
use itertools::Itertools;
use smol_str::SmolStr; use smol_str::SmolStr;
use { use {
SyntaxNode, SyntaxRoot, TreeRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot, SyntaxError,
SyntaxKind::*, SyntaxKind::*,
}; };
pub use self::generated::*; pub use self::generated::*;
@ -14,6 +15,9 @@ pub trait AstNode<R: TreeRoot> {
fn cast(syntax: SyntaxNode<R>) -> Option<Self> fn cast(syntax: SyntaxNode<R>) -> Option<Self>
where Self: Sized; where Self: Sized;
fn syntax(&self) -> &SyntaxNode<R>; fn syntax(&self) -> &SyntaxNode<R>;
fn syntax_ref<'a>(&'a self) -> SyntaxNodeRef<'a> where R: 'a {
self.syntax().as_ref()
}
} }
pub trait NameOwner<R: TreeRoot>: AstNode<R> { pub trait NameOwner<R: TreeRoot>: AstNode<R> {
@ -25,6 +29,14 @@ pub trait NameOwner<R: TreeRoot>: AstNode<R> {
} }
} }
pub trait AttrsOwner<R: TreeRoot>: AstNode<R> {
fn attrs<'a>(&'a self) -> Box<Iterator<Item=Attr<R>> + 'a> where R: 'a {
let it = self.syntax().children()
.filter_map(Attr::cast);
Box::new(it)
}
}
impl File<Arc<SyntaxRoot>> { impl File<Arc<SyntaxRoot>> {
pub fn parse(text: &str) -> Self { pub fn parse(text: &str) -> Self {
File::cast(::parse(text)).unwrap() File::cast(::parse(text)).unwrap()
@ -39,31 +51,20 @@ impl<R: TreeRoot> File<R> {
impl<R: TreeRoot> FnDef<R> { impl<R: TreeRoot> FnDef<R> {
pub fn has_atom_attr(&self, atom: &str) -> bool { pub fn has_atom_attr(&self, atom: &str) -> bool {
self.syntax() self.attrs()
.children() .filter_map(|x| x.value())
.filter(|node| node.kind() == ATTR) .filter_map(|x| as_atom(x))
.any(|attr| { .any(|x| x == atom)
let mut metas = attr.children().filter(|node| node.kind() == META_ITEM); }
let meta = match metas.next() { }
None => return false,
Some(meta) => { fn as_atom<R: TreeRoot>(tt: TokenTree<R>) -> Option<SmolStr> {
if metas.next().is_some() { let syntax = tt.syntax_ref();
return false; let (_bra, attr, _ket) = syntax.children().collect_tuple()?;
} if attr.kind() == IDENT {
meta Some(attr.leaf_text().unwrap())
} } else {
}; None
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
}
}
})
} }
} }

View file

@ -221,24 +221,26 @@ Grammar(
["functions", "FnDef"] ["functions", "FnDef"]
] ]
), ),
"FnDef": ( traits: ["NameOwner"] ), "FnDef": ( traits: ["NameOwner", "AttrsOwner"] ),
"StructDef": ( "StructDef": (
traits: ["NameOwner"], traits: ["NameOwner", "AttrsOwner"],
collections: [ collections: [
["fields", "NamedField"] ["fields", "NamedField"]
] ]
), ),
"NamedField": ( traits: ["NameOwner"] ), "NamedField": ( traits: ["NameOwner", "AttrsOwner"] ),
"EnumDef": ( traits: ["NameOwner"] ), "EnumDef": ( traits: ["NameOwner", "AttrsOwner"] ),
"TraitDef": ( traits: ["NameOwner"] ), "TraitDef": ( traits: ["NameOwner", "AttrsOwner"] ),
"Module": ( traits: ["NameOwner"] ), "Module": ( traits: ["NameOwner", "AttrsOwner"] ),
"ConstDef": ( traits: ["NameOwner"] ), "ConstDef": ( traits: ["NameOwner", "AttrsOwner"] ),
"StaticDef": ( traits: ["NameOwner"] ), "StaticDef": ( traits: ["NameOwner", "AttrsOwner"] ),
"TypeDef": ( traits: ["NameOwner"] ), "TypeDef": ( traits: ["NameOwner", "AttrsOwner"] ),
"ImplItem": (), "ImplItem": (),
"Name": (), "Name": (),
"NameRef": (), "NameRef": (),
"Attr": ( options: [ ["value", "TokenTree"] ] ),
"TokenTree": (),
"ParenType": (), "ParenType": (),
"TupleType": (), "TupleType": (),

View file

@ -22,58 +22,10 @@ fn attribute(p: &mut Parser, inner: bool) {
p.bump(); p.bump();
} }
if p.expect(L_BRACK) { if p.at(L_BRACK) {
meta_item(p); items::token_tree(p);
p.expect(R_BRACK); } else {
p.error("expected `[`");
} }
attr.complete(p, ATTR); attr.complete(p, ATTR);
} }
fn meta_item(p: &mut Parser) {
if p.at(IDENT) {
let meta_item = p.start();
p.bump();
match p.current() {
EQ => {
p.bump();
if expressions::literal(p).is_none() {
p.error("expected literal");
}
}
L_PAREN => meta_item_arg_list(p),
_ => (),
}
meta_item.complete(p, META_ITEM);
} else {
p.error("expected attribute value");
}
}
fn meta_item_arg_list(p: &mut Parser) {
assert!(p.at(L_PAREN));
p.bump();
loop {
match p.current() {
EOF | R_PAREN => break,
IDENT => meta_item(p),
c => if expressions::literal(p).is_none() {
let message = "expected attribute";
if items::ITEM_FIRST.contains(c) {
p.error(message);
return;
}
let err = p.start();
p.error(message);
p.bump();
err.complete(p, ERROR);
continue;
},
}
if !p.at(R_PAREN) {
p.expect(COMMA);
}
}
p.expect(R_PAREN);
}

View file

@ -55,9 +55,6 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF
} }
} }
pub(super) const ITEM_FIRST: TokenSet =
token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND];
pub(super) enum MaybeItem { pub(super) enum MaybeItem {
None, None,
Item(SyntaxKind), Item(SyntaxKind),
@ -322,13 +319,14 @@ pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
flavor flavor
} }
fn token_tree(p: &mut Parser) { pub(super) fn token_tree(p: &mut Parser) {
let closing_paren_kind = match p.current() { let closing_paren_kind = match p.current() {
L_CURLY => R_CURLY, L_CURLY => R_CURLY,
L_PAREN => R_PAREN, L_PAREN => R_PAREN,
L_BRACK => R_BRACK, L_BRACK => R_BRACK,
_ => unreachable!(), _ => unreachable!(),
}; };
let m = p.start();
p.bump(); p.bump();
while !p.at(EOF) && !p.at(closing_paren_kind) { while !p.at(EOF) && !p.at(closing_paren_kind) {
match p.current() { match p.current() {
@ -338,4 +336,5 @@ fn token_tree(p: &mut Parser) {
} }
}; };
p.expect(closing_paren_kind); p.expect(closing_paren_kind);
m.complete(p, TOKEN_TREE);
} }

View file

@ -2,25 +2,20 @@ FILE@[0; 54)
FN_DEF@[0; 31) FN_DEF@[0; 31)
ATTR@[0; 18) ATTR@[0; 18)
POUND@[0; 1) POUND@[0; 1)
L_BRACK@[1; 2) TOKEN_TREE@[1; 18)
META_ITEM@[2; 17) L_BRACK@[1; 2)
IDENT@[2; 5) "foo" IDENT@[2; 5) "foo"
L_PAREN@[5; 6) TOKEN_TREE@[5; 17)
META_ITEM@[6; 9) L_PAREN@[5; 6)
IDENT@[6; 9) "foo" IDENT@[6; 9) "foo"
COMMA@[9; 10) COMMA@[9; 10)
WHITESPACE@[10; 11) WHITESPACE@[10; 11)
err: `expected attribute`
ERROR@[11; 12)
PLUS@[11; 12) PLUS@[11; 12)
err: `expected attribute`
ERROR@[12; 13)
COMMA@[12; 13) COMMA@[12; 13)
WHITESPACE@[13; 14) WHITESPACE@[13; 14)
LITERAL@[14; 16)
INT_NUMBER@[14; 16) "92" INT_NUMBER@[14; 16) "92"
R_PAREN@[16; 17) R_PAREN@[16; 17)
R_BRACK@[17; 18) R_BRACK@[17; 18)
WHITESPACE@[18; 19) WHITESPACE@[18; 19)
FN_KW@[19; 21) FN_KW@[19; 21)
WHITESPACE@[21; 22) WHITESPACE@[21; 22)
@ -35,26 +30,26 @@ FILE@[0; 54)
WHITESPACE@[29; 30) WHITESPACE@[29; 30)
R_CURLY@[30; 31) R_CURLY@[30; 31)
WHITESPACE@[31; 34) WHITESPACE@[31; 34)
FN_DEF@[34; 53) ATTR@[34; 53)
ATTR@[34; 40) POUND@[34; 35)
POUND@[34; 35) TOKEN_TREE@[35; 53)
L_BRACK@[35; 36) L_BRACK@[35; 36)
META_ITEM@[36; 40) IDENT@[36; 39) "foo"
IDENT@[36; 39) "foo" TOKEN_TREE@[39; 53)
L_PAREN@[39; 40) L_PAREN@[39; 40)
err: `expected attribute` WHITESPACE@[40; 41)
err: `expected R_BRACK` FN_KW@[41; 43)
WHITESPACE@[40; 41) WHITESPACE@[43; 44)
FN_KW@[41; 43) IDENT@[44; 47) "foo"
WHITESPACE@[43; 44) TOKEN_TREE@[47; 49)
NAME@[44; 47) L_PAREN@[47; 48)
IDENT@[44; 47) "foo" R_PAREN@[48; 49)
PARAM_LIST@[47; 49) WHITESPACE@[49; 50)
L_PAREN@[47; 48) TOKEN_TREE@[50; 53)
R_PAREN@[48; 49) L_CURLY@[50; 51)
WHITESPACE@[49; 50) WHITESPACE@[51; 52)
BLOCK_EXPR@[50; 53) R_CURLY@[52; 53)
L_CURLY@[50; 51) err: `expected R_PAREN`
WHITESPACE@[51; 52) err: `expected R_BRACK`
R_CURLY@[52; 53) err: `expected an item`
WHITESPACE@[53; 54) WHITESPACE@[53; 54)

View file

@ -19,9 +19,10 @@ FILE@[0; 95)
NAME_REF@[14; 17) NAME_REF@[14; 17)
IDENT@[14; 17) "bar" IDENT@[14; 17) "bar"
err: `expected EXCL` err: `expected EXCL`
L_PAREN@[17; 18) TOKEN_TREE@[17; 19)
R_PAREN@[18; 19) L_PAREN@[17; 18)
err: `expected SEMI` R_PAREN@[18; 19)
err: `expected SEMI`
WHITESPACE@[19; 20) WHITESPACE@[19; 20)
err: `expected an item` err: `expected an item`
ERROR@[20; 80) ERROR@[20; 80)

View file

@ -86,8 +86,9 @@ FILE@[0; 91)
NAME_REF@[78; 84) NAME_REF@[78; 84)
IDENT@[78; 84) "format" IDENT@[78; 84) "format"
EXCL@[84; 85) EXCL@[84; 85)
L_PAREN@[85; 86) TOKEN_TREE@[85; 87)
R_PAREN@[86; 87) L_PAREN@[85; 86)
R_PAREN@[86; 87)
SEMI@[87; 88) SEMI@[87; 88)
WHITESPACE@[88; 89) WHITESPACE@[88; 89)
R_CURLY@[89; 90) R_CURLY@[89; 90)

View file

@ -21,8 +21,9 @@ FILE@[0; 70)
WHITESPACE@[24; 25) WHITESPACE@[24; 25)
IDENT@[25; 28) "foo" IDENT@[25; 28) "foo"
WHITESPACE@[28; 29) WHITESPACE@[28; 29)
L_CURLY@[29; 30) TOKEN_TREE@[29; 31)
R_CURLY@[30; 31) L_CURLY@[29; 30)
R_CURLY@[30; 31)
WHITESPACE@[31; 32) WHITESPACE@[31; 32)
MACRO_CALL@[32; 44) MACRO_CALL@[32; 44)
PATH@[32; 40) PATH@[32; 40)
@ -35,8 +36,9 @@ FILE@[0; 70)
NAME_REF@[37; 40) NAME_REF@[37; 40)
IDENT@[37; 40) "bar" IDENT@[37; 40) "bar"
EXCL@[40; 41) EXCL@[40; 41)
L_PAREN@[41; 42) TOKEN_TREE@[41; 43)
R_PAREN@[42; 43) L_PAREN@[41; 42)
R_PAREN@[42; 43)
SEMI@[43; 44) SEMI@[43; 44)
WHITESPACE@[44; 45) WHITESPACE@[44; 45)
MACRO_CALL@[45; 59) MACRO_CALL@[45; 59)
@ -50,8 +52,9 @@ FILE@[0; 70)
IDENT@[52; 55) "baz" IDENT@[52; 55) "baz"
EXCL@[55; 56) EXCL@[55; 56)
WHITESPACE@[56; 57) WHITESPACE@[56; 57)
L_CURLY@[57; 58) TOKEN_TREE@[57; 59)
R_CURLY@[58; 59) L_CURLY@[57; 58)
R_CURLY@[58; 59)
WHITESPACE@[59; 60) WHITESPACE@[59; 60)
STRUCT_DEF@[60; 69) STRUCT_DEF@[60; 69)
STRUCT_KW@[60; 66) STRUCT_KW@[60; 66)

View file

@ -2,175 +2,163 @@ FILE@[0; 236)
ATTR@[0; 8) ATTR@[0; 8)
POUND@[0; 1) POUND@[0; 1)
EXCL@[1; 2) EXCL@[1; 2)
L_BRACK@[2; 3) TOKEN_TREE@[2; 8)
META_ITEM@[3; 7) L_BRACK@[2; 3)
IDENT@[3; 7) "attr" IDENT@[3; 7) "attr"
R_BRACK@[7; 8) R_BRACK@[7; 8)
WHITESPACE@[8; 9) WHITESPACE@[8; 9)
ATTR@[9; 23) ATTR@[9; 23)
POUND@[9; 10) POUND@[9; 10)
EXCL@[10; 11) EXCL@[10; 11)
L_BRACK@[11; 12) TOKEN_TREE@[11; 23)
META_ITEM@[12; 22) L_BRACK@[11; 12)
IDENT@[12; 16) "attr" IDENT@[12; 16) "attr"
L_PAREN@[16; 17) TOKEN_TREE@[16; 22)
LITERAL@[17; 21) L_PAREN@[16; 17)
TRUE_KW@[17; 21) TRUE_KW@[17; 21)
R_PAREN@[21; 22) R_PAREN@[21; 22)
R_BRACK@[22; 23) R_BRACK@[22; 23)
WHITESPACE@[23; 24) WHITESPACE@[23; 24)
ATTR@[24; 39) ATTR@[24; 39)
POUND@[24; 25) POUND@[24; 25)
EXCL@[25; 26) EXCL@[25; 26)
L_BRACK@[26; 27) TOKEN_TREE@[26; 39)
META_ITEM@[27; 38) L_BRACK@[26; 27)
IDENT@[27; 31) "attr" IDENT@[27; 31) "attr"
L_PAREN@[31; 32) TOKEN_TREE@[31; 38)
META_ITEM@[32; 37) L_PAREN@[31; 32)
IDENT@[32; 37) "ident" IDENT@[32; 37) "ident"
R_PAREN@[37; 38) R_PAREN@[37; 38)
R_BRACK@[38; 39) R_BRACK@[38; 39)
WHITESPACE@[39; 40) WHITESPACE@[39; 40)
ATTR@[40; 116) ATTR@[40; 116)
POUND@[40; 41) POUND@[40; 41)
EXCL@[41; 42) EXCL@[41; 42)
L_BRACK@[42; 43) TOKEN_TREE@[42; 116)
META_ITEM@[43; 115) L_BRACK@[42; 43)
IDENT@[43; 47) "attr" IDENT@[43; 47) "attr"
L_PAREN@[47; 48) TOKEN_TREE@[47; 115)
META_ITEM@[48; 53) L_PAREN@[47; 48)
IDENT@[48; 53) "ident" IDENT@[48; 53) "ident"
COMMA@[53; 54) COMMA@[53; 54)
WHITESPACE@[54; 55) WHITESPACE@[54; 55)
LITERAL@[55; 58)
INT_NUMBER@[55; 58) "100" INT_NUMBER@[55; 58) "100"
COMMA@[58; 59) COMMA@[58; 59)
WHITESPACE@[59; 60) WHITESPACE@[59; 60)
LITERAL@[60; 64)
TRUE_KW@[60; 64) TRUE_KW@[60; 64)
COMMA@[64; 65) COMMA@[64; 65)
WHITESPACE@[65; 66) WHITESPACE@[65; 66)
LITERAL@[66; 72)
STRING@[66; 72) STRING@[66; 72)
COMMA@[72; 73) COMMA@[72; 73)
WHITESPACE@[73; 74) WHITESPACE@[73; 74)
META_ITEM@[74; 85)
IDENT@[74; 79) "ident" IDENT@[74; 79) "ident"
WHITESPACE@[79; 80) WHITESPACE@[79; 80)
EQ@[80; 81) EQ@[80; 81)
WHITESPACE@[81; 82) WHITESPACE@[81; 82)
LITERAL@[82; 85) INT_NUMBER@[82; 85) "100"
INT_NUMBER@[82; 85) "100" COMMA@[85; 86)
COMMA@[85; 86) WHITESPACE@[86; 87)
WHITESPACE@[86; 87)
META_ITEM@[87; 102)
IDENT@[87; 92) "ident" IDENT@[87; 92) "ident"
WHITESPACE@[92; 93) WHITESPACE@[92; 93)
EQ@[93; 94) EQ@[93; 94)
WHITESPACE@[94; 95) WHITESPACE@[94; 95)
LITERAL@[95; 102) STRING@[95; 102)
STRING@[95; 102) COMMA@[102; 103)
COMMA@[102; 103) WHITESPACE@[103; 104)
WHITESPACE@[103; 104)
META_ITEM@[104; 114)
IDENT@[104; 109) "ident" IDENT@[104; 109) "ident"
L_PAREN@[109; 110) TOKEN_TREE@[109; 114)
LITERAL@[110; 113) L_PAREN@[109; 110)
INT_NUMBER@[110; 113) "100" INT_NUMBER@[110; 113) "100"
R_PAREN@[113; 114) R_PAREN@[113; 114)
R_PAREN@[114; 115) R_PAREN@[114; 115)
R_BRACK@[115; 116) R_BRACK@[115; 116)
WHITESPACE@[116; 117) WHITESPACE@[116; 117)
ATTR@[117; 130) ATTR@[117; 130)
POUND@[117; 118) POUND@[117; 118)
EXCL@[118; 119) EXCL@[118; 119)
L_BRACK@[119; 120) TOKEN_TREE@[119; 130)
META_ITEM@[120; 129) L_BRACK@[119; 120)
IDENT@[120; 124) "attr" IDENT@[120; 124) "attr"
L_PAREN@[124; 125) TOKEN_TREE@[124; 129)
LITERAL@[125; 128) L_PAREN@[124; 125)
INT_NUMBER@[125; 128) "100" INT_NUMBER@[125; 128) "100"
R_PAREN@[128; 129) R_PAREN@[128; 129)
R_BRACK@[129; 130) R_BRACK@[129; 130)
WHITESPACE@[130; 131) WHITESPACE@[130; 131)
ATTR@[131; 155) ATTR@[131; 155)
POUND@[131; 132) POUND@[131; 132)
EXCL@[132; 133) EXCL@[132; 133)
L_BRACK@[133; 134) TOKEN_TREE@[133; 155)
META_ITEM@[134; 154) L_BRACK@[133; 134)
IDENT@[134; 138) "attr" IDENT@[134; 138) "attr"
L_PAREN@[138; 139) TOKEN_TREE@[138; 154)
META_ITEM@[139; 153) L_PAREN@[138; 139)
IDENT@[139; 146) "enabled" IDENT@[139; 146) "enabled"
WHITESPACE@[146; 147) WHITESPACE@[146; 147)
EQ@[147; 148) EQ@[147; 148)
WHITESPACE@[148; 149) WHITESPACE@[148; 149)
LITERAL@[149; 153) TRUE_KW@[149; 153)
TRUE_KW@[149; 153) R_PAREN@[153; 154)
R_PAREN@[153; 154) R_BRACK@[154; 155)
R_BRACK@[154; 155)
WHITESPACE@[155; 156) WHITESPACE@[155; 156)
ATTR@[156; 173) ATTR@[156; 173)
POUND@[156; 157) POUND@[156; 157)
EXCL@[157; 158) EXCL@[157; 158)
L_BRACK@[158; 159) TOKEN_TREE@[158; 173)
META_ITEM@[159; 172) L_BRACK@[158; 159)
IDENT@[159; 166) "enabled" IDENT@[159; 166) "enabled"
L_PAREN@[166; 167) TOKEN_TREE@[166; 172)
LITERAL@[167; 171) L_PAREN@[166; 167)
TRUE_KW@[167; 171) TRUE_KW@[167; 171)
R_PAREN@[171; 172) R_PAREN@[171; 172)
R_BRACK@[172; 173) R_BRACK@[172; 173)
WHITESPACE@[173; 174) WHITESPACE@[173; 174)
ATTR@[174; 191) ATTR@[174; 191)
POUND@[174; 175) POUND@[174; 175)
EXCL@[175; 176) EXCL@[175; 176)
L_BRACK@[176; 177) TOKEN_TREE@[176; 191)
META_ITEM@[177; 190) L_BRACK@[176; 177)
IDENT@[177; 181) "attr" IDENT@[177; 181) "attr"
L_PAREN@[181; 182) TOKEN_TREE@[181; 190)
LITERAL@[182; 189) L_PAREN@[181; 182)
STRING@[182; 189) STRING@[182; 189)
R_PAREN@[189; 190) R_PAREN@[189; 190)
R_BRACK@[190; 191) R_BRACK@[190; 191)
WHITESPACE@[191; 192) WHITESPACE@[191; 192)
ATTR@[192; 214) ATTR@[192; 214)
POUND@[192; 193) POUND@[192; 193)
EXCL@[193; 194) EXCL@[193; 194)
L_BRACK@[194; 195) TOKEN_TREE@[194; 214)
META_ITEM@[195; 213) L_BRACK@[194; 195)
IDENT@[195; 199) "repr" IDENT@[195; 199) "repr"
L_PAREN@[199; 200) TOKEN_TREE@[199; 213)
META_ITEM@[200; 201) L_PAREN@[199; 200)
IDENT@[200; 201) "C" IDENT@[200; 201) "C"
COMMA@[201; 202) COMMA@[201; 202)
WHITESPACE@[202; 203) WHITESPACE@[202; 203)
META_ITEM@[203; 212)
IDENT@[203; 208) "align" IDENT@[203; 208) "align"
WHITESPACE@[208; 209) WHITESPACE@[208; 209)
EQ@[209; 210) EQ@[209; 210)
WHITESPACE@[210; 211) WHITESPACE@[210; 211)
LITERAL@[211; 212) INT_NUMBER@[211; 212) "4"
INT_NUMBER@[211; 212) "4" R_PAREN@[212; 213)
R_PAREN@[212; 213) R_BRACK@[213; 214)
R_BRACK@[213; 214)
WHITESPACE@[214; 215) WHITESPACE@[214; 215)
ATTR@[215; 236) ATTR@[215; 236)
POUND@[215; 216) POUND@[215; 216)
EXCL@[216; 217) EXCL@[216; 217)
L_BRACK@[217; 218) TOKEN_TREE@[217; 236)
META_ITEM@[218; 235) L_BRACK@[217; 218)
IDENT@[218; 222) "repr" IDENT@[218; 222) "repr"
L_PAREN@[222; 223) TOKEN_TREE@[222; 235)
META_ITEM@[223; 224) L_PAREN@[222; 223)
IDENT@[223; 224) "C" IDENT@[223; 224) "C"
COMMA@[224; 225) COMMA@[224; 225)
WHITESPACE@[225; 226) WHITESPACE@[225; 226)
META_ITEM@[226; 234)
IDENT@[226; 231) "align" IDENT@[226; 231) "align"
L_PAREN@[231; 232) TOKEN_TREE@[231; 234)
LITERAL@[232; 233) L_PAREN@[231; 232)
INT_NUMBER@[232; 233) "4" INT_NUMBER@[232; 233) "4"
R_PAREN@[233; 234) R_PAREN@[233; 234)
R_PAREN@[234; 235) R_PAREN@[234; 235)
R_BRACK@[235; 236) R_BRACK@[235; 236)

View file

@ -60,10 +60,10 @@ FILE@[0; 118)
ATTR@[79; 87) ATTR@[79; 87)
POUND@[79; 80) POUND@[79; 80)
EXCL@[80; 81) EXCL@[80; 81)
L_BRACK@[81; 82) TOKEN_TREE@[81; 87)
META_ITEM@[82; 86) L_BRACK@[81; 82)
IDENT@[82; 86) "attr" IDENT@[82; 86) "attr"
R_BRACK@[86; 87) R_BRACK@[86; 87)
WHITESPACE@[87; 92) WHITESPACE@[87; 92)
MODULE@[92; 98) MODULE@[92; 98)
MOD_KW@[92; 95) MOD_KW@[92; 95)

View file

@ -2,21 +2,21 @@ FILE@[0; 35)
FN_DEF@[0; 34) FN_DEF@[0; 34)
ATTR@[0; 12) ATTR@[0; 12)
POUND@[0; 1) POUND@[0; 1)
L_BRACK@[1; 2) TOKEN_TREE@[1; 12)
META_ITEM@[2; 11) L_BRACK@[1; 2)
IDENT@[2; 5) "cfg" IDENT@[2; 5) "cfg"
L_PAREN@[5; 6) TOKEN_TREE@[5; 11)
META_ITEM@[6; 10) L_PAREN@[5; 6)
IDENT@[6; 10) "test" IDENT@[6; 10) "test"
R_PAREN@[10; 11) R_PAREN@[10; 11)
R_BRACK@[11; 12) R_BRACK@[11; 12)
WHITESPACE@[12; 13) WHITESPACE@[12; 13)
ATTR@[13; 22) ATTR@[13; 22)
POUND@[13; 14) POUND@[13; 14)
L_BRACK@[14; 15) TOKEN_TREE@[14; 22)
META_ITEM@[15; 21) L_BRACK@[14; 15)
IDENT@[15; 21) "ignore" IDENT@[15; 21) "ignore"
R_BRACK@[21; 22) R_BRACK@[21; 22)
WHITESPACE@[22; 23) WHITESPACE@[22; 23)
FN_KW@[23; 25) FN_KW@[23; 25)
WHITESPACE@[25; 26) WHITESPACE@[25; 26)

View file

@ -2,15 +2,15 @@ FILE@[0; 23)
FN_DEF@[0; 22) FN_DEF@[0; 22)
ATTR@[0; 10) ATTR@[0; 10)
POUND@[0; 1) POUND@[0; 1)
L_BRACK@[1; 2) TOKEN_TREE@[1; 10)
META_ITEM@[2; 9) L_BRACK@[1; 2)
IDENT@[2; 5) "foo" IDENT@[2; 5) "foo"
L_PAREN@[5; 6) TOKEN_TREE@[5; 9)
META_ITEM@[6; 7) L_PAREN@[5; 6)
IDENT@[6; 7) "a" IDENT@[6; 7) "a"
COMMA@[7; 8) COMMA@[7; 8)
R_PAREN@[8; 9) R_PAREN@[8; 9)
R_BRACK@[9; 10) R_BRACK@[9; 10)
WHITESPACE@[10; 11) WHITESPACE@[10; 11)
FN_KW@[11; 13) FN_KW@[11; 13)
WHITESPACE@[13; 14) WHITESPACE@[13; 14)

View file

@ -70,19 +70,19 @@ fn assert_equal_text(expected: &str, actual: &str, path: &Path) {
return; return;
} }
let dir = project_dir(); let dir = project_dir();
let path = path.strip_prefix(&dir).unwrap_or_else(|_| path); let pretty_path = path.strip_prefix(&dir).unwrap_or_else(|_| path);
if expected.trim() == actual.trim() { if expected.trim() == actual.trim() {
println!("whitespace difference, rewriting"); println!("whitespace difference, rewriting");
println!("file: {}\n", path.display()); println!("file: {}\n", pretty_path.display());
fs::write(path, actual).unwrap(); fs::write(path, actual).unwrap();
return; return;
} }
if REWRITE { if REWRITE {
println!("rewriting {}", path.display()); println!("rewriting {}", pretty_path.display());
fs::write(path, actual).unwrap(); fs::write(path, actual).unwrap();
return; return;
} }
assert_eq_text!(expected, actual, "file: {}", path.display()); assert_eq_text!(expected, actual, "file: {}", pretty_path.display());
} }
fn collect_tests(paths: &[&str]) -> Vec<PathBuf> { fn collect_tests(paths: &[&str]) -> Vec<PathBuf> {