From 50b9012e10d2fa74294547c25642b4a69fed4bda Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sat, 27 Jan 2018 20:29:14 -0500 Subject: [PATCH 1/2] Add minimal docs to most public symbols --- src/lexer/mod.rs | 2 ++ src/lib.rs | 20 ++++++++++++++++++++ src/parser/mod.rs | 1 + src/text.rs | 11 +++++++++++ src/tree/file_builder.rs | 5 +++++ src/tree/mod.rs | 24 +++++++++++++++++++++--- 6 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index 2f8d3a402c52..65a99432791a 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -17,6 +17,7 @@ use self::strings::{is_string_literal_start, scan_byte_char_or_string, scan_char mod comments; use self::comments::{scan_comment, scan_shebang}; +/// Break a string up into its component tokens pub fn tokenize(text: &str) -> Vec { let mut text = text; let mut acc = Vec::new(); @@ -28,6 +29,7 @@ pub fn tokenize(text: &str) -> Vec { } acc } +/// Get the next token from a string pub fn next_token(text: &str) -> Token { assert!(!text.is_empty()); let mut ptr = Ptr::new(text); diff --git a/src/lib.rs b/src/lib.rs index 39b01a1cb38a..87a9d11eaf5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,20 @@ +//! An experimental implementation of [Rust RFC#2256 libsyntax2.0][rfc#2256]. +//! +//! The intent is to be an IDE-ready parser, i.e. one that offers +//! +//! - easy and fast incremental re-parsing, +//! - graceful handling of errors, and +//! - maintains all information in the source file. +//! +//! For more information, see [the RFC][rfc#2265], or [the working draft][RFC.md]. +//! +//! [rfc#2256]: +//! [RFC.md]: + +#![forbid(missing_debug_implementations, unconditional_recursion, future_incompatible)] +#![deny(bad_style, unsafe_code, missing_docs)] +//#![warn(unreachable_pub)] // rust-lang/rust#47816 + extern crate unicode_xid; mod text; @@ -6,17 +23,20 @@ mod lexer; mod parser; #[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(missing_docs)] pub mod syntax_kinds; pub use text::{TextRange, TextUnit}; pub use tree::{File, FileBuilder, Node, Sink, SyntaxKind, Token}; pub use lexer::{next_token, tokenize}; pub use parser::parse; +/// Utilities for simple uses of the parser. pub mod utils { use std::fmt::Write; use {File, Node}; + /// Parse a file and create a string representation of the resulting parse tree. pub fn dump_tree(file: &File) -> String { let mut result = String::new(); go(file.root(), &mut result, 0); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d04ed1e75c93..0f8f2ce0cc71 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6,6 +6,7 @@ use tree::TOMBSTONE; mod event_parser; use self::event_parser::Event; +/// Parse a sequence of tokens into the representative node tree pub fn parse(text: String, tokens: &[Token]) -> File { let events = event_parser::parse(&text, tokens); from_events_to_file(text, tokens, events) diff --git a/src/text.rs b/src/text.rs index ac1a54a75820..4084bf44e8f9 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1,14 +1,17 @@ use std::fmt; use std::ops; +/// An text position in a source file #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct TextUnit(u32); impl TextUnit { + /// The positional offset required for one character pub fn len_of_char(c: char) -> TextUnit { TextUnit(c.len_utf8() as u32) } + #[allow(missing_docs)] pub fn new(val: u32) -> TextUnit { TextUnit(val) } @@ -64,6 +67,7 @@ impl ops::SubAssign for TextUnit { } } +/// A range of text in a source file #[derive(Clone, Copy, PartialEq, Eq)] pub struct TextRange { start: TextUnit, @@ -83,10 +87,12 @@ impl fmt::Display for TextRange { } impl TextRange { + /// An length-0 range of text pub fn empty() -> TextRange { TextRange::from_to(TextUnit::new(0), TextUnit::new(0)) } + /// The left-inclusive range (`[from..to)`) between to points in the text pub fn from_to(from: TextUnit, to: TextUnit) -> TextRange { assert!(from <= to, "Invalid text range [{}; {})", from, to); TextRange { @@ -95,22 +101,27 @@ impl TextRange { } } + /// The range from some point over some length pub fn from_len(from: TextUnit, len: TextUnit) -> TextRange { TextRange::from_to(from, from + len) } + /// The starting position of this range pub fn start(&self) -> TextUnit { self.start } + /// The end position of this range pub fn end(&self) -> TextUnit { self.end } + /// The length of this range pub fn len(&self) -> TextUnit { self.end - self.start } + /// Is this range empty of any content? pub fn is_empty(&self) -> bool { self.start() == self.end() } diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index 939922cb2a8f..738705f0226f 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs @@ -1,3 +1,6 @@ +// FIXME(CAD97): I don't understand this mod well enough to stub out docs for the public symbols yet +#![allow(missing_docs)] + use {SyntaxKind, TextRange, TextUnit}; use super::{File, NodeData, NodeIdx, SyntaxErrorData}; @@ -8,6 +11,7 @@ pub trait Sink { fn error(&mut self) -> ErrorBuilder; } +#[derive(Debug)] pub struct FileBuilder { text: String, nodes: Vec, @@ -139,6 +143,7 @@ fn grow(left: &mut TextRange, right: TextRange) { *left = TextRange::from_to(left.start(), right.end()) } +#[derive(Debug)] pub struct ErrorBuilder<'f> { message: Option, builder: &'f mut FileBuilder, diff --git a/src/tree/mod.rs b/src/tree/mod.rs index a330caf54fe5..aaf048c73415 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -7,6 +7,7 @@ use std::cmp; mod file_builder; pub use self::file_builder::{FileBuilder, Sink}; +/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SyntaxKind(pub(crate) u32); @@ -37,12 +38,17 @@ pub(crate) struct SyntaxInfo { pub name: &'static str, } +/// A token of Rust source. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Token { + /// The kind of token. pub kind: SyntaxKind, + /// The length of the token. pub len: TextUnit, } +/// The contents of a Rust source file. +#[derive(Debug)] pub struct File { text: String, nodes: Vec, @@ -50,6 +56,7 @@ pub struct File { } impl File { + /// The root node of this source file. pub fn root<'f>(&'f self) -> Node<'f> { assert!(!self.nodes.is_empty()); Node { @@ -59,6 +66,7 @@ impl File { } } +/// A reference to a token in a Rust source file. #[derive(Clone, Copy)] pub struct Node<'f> { file: &'f File, @@ -66,28 +74,34 @@ pub struct Node<'f> { } impl<'f> Node<'f> { + /// The kind of the token at this node. pub fn kind(&self) -> SyntaxKind { self.data().kind } + /// The text range covered by the token at this node. pub fn range(&self) -> TextRange { self.data().range } + /// The text at this node. pub fn text(&self) -> &'f str { &self.file.text.as_str()[self.range()] } + /// The parent node to this node. pub fn parent(&self) -> Option> { self.as_node(self.data().parent) } + /// The children nodes of this node. pub fn children(&self) -> Children<'f> { Children { next: self.as_node(self.data().first_child), } } + /// Any errors contained in this node. pub fn errors(&self) -> SyntaxErrors<'f> { let pos = self.file.errors.iter().position(|e| e.node == self.idx); let next = pos.map(|i| ErrorIdx(i as u32)).map(|idx| SyntaxError { @@ -123,7 +137,7 @@ impl<'f> cmp::PartialEq> for Node<'f> { impl<'f> cmp::Eq for Node<'f> {} -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct SyntaxError<'f> { file: &'f File, idx: ErrorIdx, @@ -162,6 +176,7 @@ impl<'f> SyntaxError<'f> { } } +#[derive(Debug)] pub struct Children<'f> { next: Option>, } @@ -176,6 +191,7 @@ impl<'f> Iterator for Children<'f> { } } +#[derive(Debug)] pub struct SyntaxErrors<'f> { next: Option>, } @@ -190,9 +206,10 @@ impl<'f> Iterator for SyntaxErrors<'f> { } } -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] struct NodeIdx(u32); +#[derive(Debug)] struct NodeData { kind: SyntaxKind, range: TextRange, @@ -215,9 +232,10 @@ impl ::std::ops::IndexMut for Vec { } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] struct ErrorIdx(u32); +#[derive(Debug)] struct SyntaxErrorData { node: NodeIdx, message: String, From 4244948c6b1a62bd0e1ef276d1f0cc22c36f6f66 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sat, 27 Jan 2018 21:36:28 -0500 Subject: [PATCH 2/2] Convert SyntaxKind to an enum --- src/bin/gen.rs | 56 ++-- src/lib.rs | 2 - src/parser/event_parser/grammar/mod.rs | 1 - src/parser/event_parser/parser.rs | 3 +- src/parser/mod.rs | 1 - src/syntax_kinds.rs | 402 +++++++++++++------------ src/tree/mod.rs | 21 +- 7 files changed, 243 insertions(+), 243 deletions(-) diff --git a/src/bin/gen.rs b/src/bin/gen.rs index 8f6402f5c997..4b8a5afecf81 100644 --- a/src/bin/gen.rs +++ b/src/bin/gen.rs @@ -29,8 +29,10 @@ impl Grammar { fn to_syntax_kinds(&self) -> String { let mut acc = String::new(); - acc.push_str("// Generated from grammar.ron\n"); - acc.push_str("use tree::{SyntaxKind, SyntaxInfo};\n"); + acc.push_str("#![allow(bad_style, missing_docs, unreachable_pub)]\n"); + acc.push_str("#![cfg_attr(rustfmt, rustfmt_skip)]\n"); + acc.push_str("//! Generated from grammar.ron\n"); + acc.push_str("use tree::SyntaxInfo;\n"); acc.push_str("\n"); let syntax_kinds: Vec = self.keywords @@ -40,41 +42,49 @@ impl Grammar { .chain(self.nodes.iter().cloned()) .collect(); - for (idx, kind) in syntax_kinds.iter().enumerate() { - let sname = scream(kind); - write!( - acc, - "pub const {}: SyntaxKind = SyntaxKind({});\n", - sname, idx - ).unwrap(); + // enum SyntaxKind + acc.push_str("/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`.\n"); + acc.push_str("#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); + acc.push_str("#[repr(u32)]\n"); + acc.push_str("pub enum SyntaxKind {\n"); + for kind in syntax_kinds.iter() { + write!(acc, " {},\n", scream(kind)).unwrap(); } acc.push_str("\n"); - write!( - acc, - "static INFOS: [SyntaxInfo; {}] = [\n", - syntax_kinds.len() - ).unwrap(); + acc.push_str(" TOMBSTONE = !0 - 1,\n"); + acc.push_str(" EOF = !0,\n"); + acc.push_str("}\n"); + acc.push_str("pub(crate) use self::SyntaxKind::*;\n"); + acc.push_str("\n"); + + // fn info + acc.push_str("impl SyntaxKind {\n"); + acc.push_str(" pub(crate) fn info(self) -> &'static SyntaxInfo {\n"); + acc.push_str(" match self {\n"); for kind in syntax_kinds.iter() { let sname = scream(kind); write!( acc, - " SyntaxInfo {{ name: \"{sname}\" }},\n", + " {sname} => &SyntaxInfo {{ name: \"{sname}\" }},\n", sname = sname ).unwrap(); } - acc.push_str("];\n"); + acc.push_str("\n"); + acc.push_str(" TOMBSTONE => &SyntaxInfo { name: \"TOMBSTONE\" },\n"); + acc.push_str(" EOF => &SyntaxInfo { name: \"EOF\" },\n"); + acc.push_str(" }\n"); + acc.push_str(" }\n"); + acc.push_str("}\n"); acc.push_str("\n"); - acc.push_str("pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo {\n"); - acc.push_str(" &INFOS[kind.0 as usize]\n"); - acc.push_str("}\n\n"); + // fn ident_to_keyword acc.push_str("pub(crate) fn ident_to_keyword(ident: &str) -> Option {\n"); - acc.push_str(" match ident {\n"); + acc.push_str(" match ident {\n"); for kw in self.keywords.iter() { - write!(acc, " {:?} => Some({}),\n", kw, kw_token(kw)).unwrap(); + write!(acc, " {:?} => Some({}),\n", kw, kw_token(kw)).unwrap(); } - acc.push_str(" _ => None,\n"); - acc.push_str(" }\n"); + acc.push_str(" _ => None,\n"); + acc.push_str(" }\n"); acc.push_str("}\n"); acc } diff --git a/src/lib.rs b/src/lib.rs index 87a9d11eaf5a..ad333582cf12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,8 +22,6 @@ mod tree; mod lexer; mod parser; -#[cfg_attr(rustfmt, rustfmt_skip)] -#[allow(missing_docs)] pub mod syntax_kinds; pub use text::{TextRange, TextUnit}; pub use tree::{File, FileBuilder, Node, Sink, SyntaxKind, Token}; diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs index c6ab1fbe26eb..82f8b7f3e77c 100644 --- a/src/parser/event_parser/grammar/mod.rs +++ b/src/parser/event_parser/grammar/mod.rs @@ -1,6 +1,5 @@ use super::parser::{Parser, TokenSet}; use SyntaxKind; -use tree::EOF; use syntax_kinds::*; mod items; diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs index 5ba3071cb8ee..573e3d73a8ec 100644 --- a/src/parser/event_parser/parser.rs +++ b/src/parser/event_parser/parser.rs @@ -1,8 +1,7 @@ use {SyntaxKind, TextUnit, Token}; use super::Event; use super::super::is_insignificant; -use syntax_kinds::{ERROR, L_CURLY, R_CURLY}; -use tree::{EOF, TOMBSTONE}; +use SyntaxKind::{EOF, ERROR, L_CURLY, R_CURLY, TOMBSTONE}; pub(crate) struct Marker { pos: u32, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0f8f2ce0cc71..c5525ff9cdcd 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,7 +1,6 @@ use {File, FileBuilder, Sink, SyntaxKind, Token}; use syntax_kinds::*; -use tree::TOMBSTONE; mod event_parser; use self::event_parser::Event; diff --git a/src/syntax_kinds.rs b/src/syntax_kinds.rs index 5ab8b934b82a..aa19c2adff17 100644 --- a/src/syntax_kinds.rs +++ b/src/syntax_kinds.rs @@ -1,201 +1,215 @@ -// Generated from grammar.ron -use tree::{SyntaxKind, SyntaxInfo}; +#![allow(bad_style, missing_docs, unreachable_pub)] +#![cfg_attr(rustfmt, rustfmt_skip)] +//! Generated from grammar.ron +use tree::SyntaxInfo; -pub const USE_KW: SyntaxKind = SyntaxKind(0); -pub const FN_KW: SyntaxKind = SyntaxKind(1); -pub const STRUCT_KW: SyntaxKind = SyntaxKind(2); -pub const ENUM_KW: SyntaxKind = SyntaxKind(3); -pub const TRAIT_KW: SyntaxKind = SyntaxKind(4); -pub const IMPL_KW: SyntaxKind = SyntaxKind(5); -pub const TRUE_KW: SyntaxKind = SyntaxKind(6); -pub const FALSE_KW: SyntaxKind = SyntaxKind(7); -pub const AS_KW: SyntaxKind = SyntaxKind(8); -pub const EXTERN_KW: SyntaxKind = SyntaxKind(9); -pub const CRATE_KW: SyntaxKind = SyntaxKind(10); -pub const MOD_KW: SyntaxKind = SyntaxKind(11); -pub const PUB_KW: SyntaxKind = SyntaxKind(12); -pub const SELF_KW: SyntaxKind = SyntaxKind(13); -pub const SUPER_KW: SyntaxKind = SyntaxKind(14); -pub const IN_KW: SyntaxKind = SyntaxKind(15); -pub const WHERE_KW: SyntaxKind = SyntaxKind(16); -pub const ERROR: SyntaxKind = SyntaxKind(17); -pub const IDENT: SyntaxKind = SyntaxKind(18); -pub const UNDERSCORE: SyntaxKind = SyntaxKind(19); -pub const WHITESPACE: SyntaxKind = SyntaxKind(20); -pub const INT_NUMBER: SyntaxKind = SyntaxKind(21); -pub const FLOAT_NUMBER: SyntaxKind = SyntaxKind(22); -pub const SEMI: SyntaxKind = SyntaxKind(23); -pub const COMMA: SyntaxKind = SyntaxKind(24); -pub const DOT: SyntaxKind = SyntaxKind(25); -pub const DOTDOT: SyntaxKind = SyntaxKind(26); -pub const DOTDOTDOT: SyntaxKind = SyntaxKind(27); -pub const DOTDOTEQ: SyntaxKind = SyntaxKind(28); -pub const L_PAREN: SyntaxKind = SyntaxKind(29); -pub const R_PAREN: SyntaxKind = SyntaxKind(30); -pub const L_CURLY: SyntaxKind = SyntaxKind(31); -pub const R_CURLY: SyntaxKind = SyntaxKind(32); -pub const L_BRACK: SyntaxKind = SyntaxKind(33); -pub const R_BRACK: SyntaxKind = SyntaxKind(34); -pub const L_ANGLE: SyntaxKind = SyntaxKind(35); -pub const R_ANGLE: SyntaxKind = SyntaxKind(36); -pub const AT: SyntaxKind = SyntaxKind(37); -pub const POUND: SyntaxKind = SyntaxKind(38); -pub const TILDE: SyntaxKind = SyntaxKind(39); -pub const QUESTION: SyntaxKind = SyntaxKind(40); -pub const COLON: SyntaxKind = SyntaxKind(41); -pub const COLONCOLON: SyntaxKind = SyntaxKind(42); -pub const DOLLAR: SyntaxKind = SyntaxKind(43); -pub const EQ: SyntaxKind = SyntaxKind(44); -pub const EQEQ: SyntaxKind = SyntaxKind(45); -pub const FAT_ARROW: SyntaxKind = SyntaxKind(46); -pub const NEQ: SyntaxKind = SyntaxKind(47); -pub const EXCL: SyntaxKind = SyntaxKind(48); -pub const LIFETIME: SyntaxKind = SyntaxKind(49); -pub const CHAR: SyntaxKind = SyntaxKind(50); -pub const BYTE: SyntaxKind = SyntaxKind(51); -pub const STRING: SyntaxKind = SyntaxKind(52); -pub const RAW_STRING: SyntaxKind = SyntaxKind(53); -pub const BYTE_STRING: SyntaxKind = SyntaxKind(54); -pub const RAW_BYTE_STRING: SyntaxKind = SyntaxKind(55); -pub const PLUS: SyntaxKind = SyntaxKind(56); -pub const MINUS: SyntaxKind = SyntaxKind(57); -pub const STAR: SyntaxKind = SyntaxKind(58); -pub const SLASH: SyntaxKind = SyntaxKind(59); -pub const CARET: SyntaxKind = SyntaxKind(60); -pub const PERCENT: SyntaxKind = SyntaxKind(61); -pub const AMPERSAND: SyntaxKind = SyntaxKind(62); -pub const PIPE: SyntaxKind = SyntaxKind(63); -pub const THIN_ARROW: SyntaxKind = SyntaxKind(64); -pub const COMMENT: SyntaxKind = SyntaxKind(65); -pub const DOC_COMMENT: SyntaxKind = SyntaxKind(66); -pub const SHEBANG: SyntaxKind = SyntaxKind(67); -pub const FILE: SyntaxKind = SyntaxKind(68); -pub const STRUCT_ITEM: SyntaxKind = SyntaxKind(69); -pub const NAMED_FIELD: SyntaxKind = SyntaxKind(70); -pub const POS_FIELD: SyntaxKind = SyntaxKind(71); -pub const FN_ITEM: SyntaxKind = SyntaxKind(72); -pub const EXTERN_CRATE_ITEM: SyntaxKind = SyntaxKind(73); -pub const ATTR: SyntaxKind = SyntaxKind(74); -pub const META_ITEM: SyntaxKind = SyntaxKind(75); -pub const MOD_ITEM: SyntaxKind = SyntaxKind(76); -pub const USE_ITEM: SyntaxKind = SyntaxKind(77); -pub const USE_TREE: SyntaxKind = SyntaxKind(78); -pub const PATH: SyntaxKind = SyntaxKind(79); -pub const PATH_SEGMENT: SyntaxKind = SyntaxKind(80); -pub const LITERAL: SyntaxKind = SyntaxKind(81); -pub const ALIAS: SyntaxKind = SyntaxKind(82); -pub const VISIBILITY: SyntaxKind = SyntaxKind(83); +/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(u32)] +pub enum SyntaxKind { + USE_KW, + FN_KW, + STRUCT_KW, + ENUM_KW, + TRAIT_KW, + IMPL_KW, + TRUE_KW, + FALSE_KW, + AS_KW, + EXTERN_KW, + CRATE_KW, + MOD_KW, + PUB_KW, + SELF_KW, + SUPER_KW, + IN_KW, + WHERE_KW, + ERROR, + IDENT, + UNDERSCORE, + WHITESPACE, + INT_NUMBER, + FLOAT_NUMBER, + SEMI, + COMMA, + DOT, + DOTDOT, + DOTDOTDOT, + DOTDOTEQ, + L_PAREN, + R_PAREN, + L_CURLY, + R_CURLY, + L_BRACK, + R_BRACK, + L_ANGLE, + R_ANGLE, + AT, + POUND, + TILDE, + QUESTION, + COLON, + COLONCOLON, + DOLLAR, + EQ, + EQEQ, + FAT_ARROW, + NEQ, + EXCL, + LIFETIME, + CHAR, + BYTE, + STRING, + RAW_STRING, + BYTE_STRING, + RAW_BYTE_STRING, + PLUS, + MINUS, + STAR, + SLASH, + CARET, + PERCENT, + AMPERSAND, + PIPE, + THIN_ARROW, + COMMENT, + DOC_COMMENT, + SHEBANG, + FILE, + STRUCT_ITEM, + NAMED_FIELD, + POS_FIELD, + FN_ITEM, + EXTERN_CRATE_ITEM, + ATTR, + META_ITEM, + MOD_ITEM, + USE_ITEM, + USE_TREE, + PATH, + PATH_SEGMENT, + LITERAL, + ALIAS, + VISIBILITY, -static INFOS: [SyntaxInfo; 84] = [ - SyntaxInfo { name: "USE_KW" }, - SyntaxInfo { name: "FN_KW" }, - SyntaxInfo { name: "STRUCT_KW" }, - SyntaxInfo { name: "ENUM_KW" }, - SyntaxInfo { name: "TRAIT_KW" }, - SyntaxInfo { name: "IMPL_KW" }, - SyntaxInfo { name: "TRUE_KW" }, - SyntaxInfo { name: "FALSE_KW" }, - SyntaxInfo { name: "AS_KW" }, - SyntaxInfo { name: "EXTERN_KW" }, - SyntaxInfo { name: "CRATE_KW" }, - SyntaxInfo { name: "MOD_KW" }, - SyntaxInfo { name: "PUB_KW" }, - SyntaxInfo { name: "SELF_KW" }, - SyntaxInfo { name: "SUPER_KW" }, - SyntaxInfo { name: "IN_KW" }, - SyntaxInfo { name: "WHERE_KW" }, - SyntaxInfo { name: "ERROR" }, - SyntaxInfo { name: "IDENT" }, - SyntaxInfo { name: "UNDERSCORE" }, - SyntaxInfo { name: "WHITESPACE" }, - SyntaxInfo { name: "INT_NUMBER" }, - SyntaxInfo { name: "FLOAT_NUMBER" }, - SyntaxInfo { name: "SEMI" }, - SyntaxInfo { name: "COMMA" }, - SyntaxInfo { name: "DOT" }, - SyntaxInfo { name: "DOTDOT" }, - SyntaxInfo { name: "DOTDOTDOT" }, - SyntaxInfo { name: "DOTDOTEQ" }, - SyntaxInfo { name: "L_PAREN" }, - SyntaxInfo { name: "R_PAREN" }, - SyntaxInfo { name: "L_CURLY" }, - SyntaxInfo { name: "R_CURLY" }, - SyntaxInfo { name: "L_BRACK" }, - SyntaxInfo { name: "R_BRACK" }, - SyntaxInfo { name: "L_ANGLE" }, - SyntaxInfo { name: "R_ANGLE" }, - SyntaxInfo { name: "AT" }, - SyntaxInfo { name: "POUND" }, - SyntaxInfo { name: "TILDE" }, - SyntaxInfo { name: "QUESTION" }, - SyntaxInfo { name: "COLON" }, - SyntaxInfo { name: "COLONCOLON" }, - SyntaxInfo { name: "DOLLAR" }, - SyntaxInfo { name: "EQ" }, - SyntaxInfo { name: "EQEQ" }, - SyntaxInfo { name: "FAT_ARROW" }, - SyntaxInfo { name: "NEQ" }, - SyntaxInfo { name: "EXCL" }, - SyntaxInfo { name: "LIFETIME" }, - SyntaxInfo { name: "CHAR" }, - SyntaxInfo { name: "BYTE" }, - SyntaxInfo { name: "STRING" }, - SyntaxInfo { name: "RAW_STRING" }, - SyntaxInfo { name: "BYTE_STRING" }, - SyntaxInfo { name: "RAW_BYTE_STRING" }, - SyntaxInfo { name: "PLUS" }, - SyntaxInfo { name: "MINUS" }, - SyntaxInfo { name: "STAR" }, - SyntaxInfo { name: "SLASH" }, - SyntaxInfo { name: "CARET" }, - SyntaxInfo { name: "PERCENT" }, - SyntaxInfo { name: "AMPERSAND" }, - SyntaxInfo { name: "PIPE" }, - SyntaxInfo { name: "THIN_ARROW" }, - SyntaxInfo { name: "COMMENT" }, - SyntaxInfo { name: "DOC_COMMENT" }, - SyntaxInfo { name: "SHEBANG" }, - SyntaxInfo { name: "FILE" }, - SyntaxInfo { name: "STRUCT_ITEM" }, - SyntaxInfo { name: "NAMED_FIELD" }, - SyntaxInfo { name: "POS_FIELD" }, - SyntaxInfo { name: "FN_ITEM" }, - SyntaxInfo { name: "EXTERN_CRATE_ITEM" }, - SyntaxInfo { name: "ATTR" }, - SyntaxInfo { name: "META_ITEM" }, - SyntaxInfo { name: "MOD_ITEM" }, - SyntaxInfo { name: "USE_ITEM" }, - SyntaxInfo { name: "USE_TREE" }, - SyntaxInfo { name: "PATH" }, - SyntaxInfo { name: "PATH_SEGMENT" }, - SyntaxInfo { name: "LITERAL" }, - SyntaxInfo { name: "ALIAS" }, - SyntaxInfo { name: "VISIBILITY" }, -]; + TOMBSTONE = !0 - 1, + EOF = !0, +} +pub(crate) use self::SyntaxKind::*; + +impl SyntaxKind { + pub(crate) fn info(self) -> &'static SyntaxInfo { + match self { + USE_KW => &SyntaxInfo { name: "USE_KW" }, + FN_KW => &SyntaxInfo { name: "FN_KW" }, + STRUCT_KW => &SyntaxInfo { name: "STRUCT_KW" }, + ENUM_KW => &SyntaxInfo { name: "ENUM_KW" }, + TRAIT_KW => &SyntaxInfo { name: "TRAIT_KW" }, + IMPL_KW => &SyntaxInfo { name: "IMPL_KW" }, + TRUE_KW => &SyntaxInfo { name: "TRUE_KW" }, + FALSE_KW => &SyntaxInfo { name: "FALSE_KW" }, + AS_KW => &SyntaxInfo { name: "AS_KW" }, + EXTERN_KW => &SyntaxInfo { name: "EXTERN_KW" }, + CRATE_KW => &SyntaxInfo { name: "CRATE_KW" }, + MOD_KW => &SyntaxInfo { name: "MOD_KW" }, + PUB_KW => &SyntaxInfo { name: "PUB_KW" }, + SELF_KW => &SyntaxInfo { name: "SELF_KW" }, + SUPER_KW => &SyntaxInfo { name: "SUPER_KW" }, + IN_KW => &SyntaxInfo { name: "IN_KW" }, + WHERE_KW => &SyntaxInfo { name: "WHERE_KW" }, + ERROR => &SyntaxInfo { name: "ERROR" }, + IDENT => &SyntaxInfo { name: "IDENT" }, + UNDERSCORE => &SyntaxInfo { name: "UNDERSCORE" }, + WHITESPACE => &SyntaxInfo { name: "WHITESPACE" }, + INT_NUMBER => &SyntaxInfo { name: "INT_NUMBER" }, + FLOAT_NUMBER => &SyntaxInfo { name: "FLOAT_NUMBER" }, + SEMI => &SyntaxInfo { name: "SEMI" }, + COMMA => &SyntaxInfo { name: "COMMA" }, + DOT => &SyntaxInfo { name: "DOT" }, + DOTDOT => &SyntaxInfo { name: "DOTDOT" }, + DOTDOTDOT => &SyntaxInfo { name: "DOTDOTDOT" }, + DOTDOTEQ => &SyntaxInfo { name: "DOTDOTEQ" }, + L_PAREN => &SyntaxInfo { name: "L_PAREN" }, + R_PAREN => &SyntaxInfo { name: "R_PAREN" }, + L_CURLY => &SyntaxInfo { name: "L_CURLY" }, + R_CURLY => &SyntaxInfo { name: "R_CURLY" }, + L_BRACK => &SyntaxInfo { name: "L_BRACK" }, + R_BRACK => &SyntaxInfo { name: "R_BRACK" }, + L_ANGLE => &SyntaxInfo { name: "L_ANGLE" }, + R_ANGLE => &SyntaxInfo { name: "R_ANGLE" }, + AT => &SyntaxInfo { name: "AT" }, + POUND => &SyntaxInfo { name: "POUND" }, + TILDE => &SyntaxInfo { name: "TILDE" }, + QUESTION => &SyntaxInfo { name: "QUESTION" }, + COLON => &SyntaxInfo { name: "COLON" }, + COLONCOLON => &SyntaxInfo { name: "COLONCOLON" }, + DOLLAR => &SyntaxInfo { name: "DOLLAR" }, + EQ => &SyntaxInfo { name: "EQ" }, + EQEQ => &SyntaxInfo { name: "EQEQ" }, + FAT_ARROW => &SyntaxInfo { name: "FAT_ARROW" }, + NEQ => &SyntaxInfo { name: "NEQ" }, + EXCL => &SyntaxInfo { name: "EXCL" }, + LIFETIME => &SyntaxInfo { name: "LIFETIME" }, + CHAR => &SyntaxInfo { name: "CHAR" }, + BYTE => &SyntaxInfo { name: "BYTE" }, + STRING => &SyntaxInfo { name: "STRING" }, + RAW_STRING => &SyntaxInfo { name: "RAW_STRING" }, + BYTE_STRING => &SyntaxInfo { name: "BYTE_STRING" }, + RAW_BYTE_STRING => &SyntaxInfo { name: "RAW_BYTE_STRING" }, + PLUS => &SyntaxInfo { name: "PLUS" }, + MINUS => &SyntaxInfo { name: "MINUS" }, + STAR => &SyntaxInfo { name: "STAR" }, + SLASH => &SyntaxInfo { name: "SLASH" }, + CARET => &SyntaxInfo { name: "CARET" }, + PERCENT => &SyntaxInfo { name: "PERCENT" }, + AMPERSAND => &SyntaxInfo { name: "AMPERSAND" }, + PIPE => &SyntaxInfo { name: "PIPE" }, + THIN_ARROW => &SyntaxInfo { name: "THIN_ARROW" }, + COMMENT => &SyntaxInfo { name: "COMMENT" }, + DOC_COMMENT => &SyntaxInfo { name: "DOC_COMMENT" }, + SHEBANG => &SyntaxInfo { name: "SHEBANG" }, + FILE => &SyntaxInfo { name: "FILE" }, + STRUCT_ITEM => &SyntaxInfo { name: "STRUCT_ITEM" }, + NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, + POS_FIELD => &SyntaxInfo { name: "POS_FIELD" }, + FN_ITEM => &SyntaxInfo { name: "FN_ITEM" }, + EXTERN_CRATE_ITEM => &SyntaxInfo { name: "EXTERN_CRATE_ITEM" }, + ATTR => &SyntaxInfo { name: "ATTR" }, + META_ITEM => &SyntaxInfo { name: "META_ITEM" }, + MOD_ITEM => &SyntaxInfo { name: "MOD_ITEM" }, + USE_ITEM => &SyntaxInfo { name: "USE_ITEM" }, + USE_TREE => &SyntaxInfo { name: "USE_TREE" }, + PATH => &SyntaxInfo { name: "PATH" }, + PATH_SEGMENT => &SyntaxInfo { name: "PATH_SEGMENT" }, + LITERAL => &SyntaxInfo { name: "LITERAL" }, + ALIAS => &SyntaxInfo { name: "ALIAS" }, + VISIBILITY => &SyntaxInfo { name: "VISIBILITY" }, -pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo { - &INFOS[kind.0 as usize] + TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, + EOF => &SyntaxInfo { name: "EOF" }, + } + } } pub(crate) fn ident_to_keyword(ident: &str) -> Option { - match ident { - "use" => Some(USE_KW), - "fn" => Some(FN_KW), - "struct" => Some(STRUCT_KW), - "enum" => Some(ENUM_KW), - "trait" => Some(TRAIT_KW), - "impl" => Some(IMPL_KW), - "true" => Some(TRUE_KW), - "false" => Some(FALSE_KW), - "as" => Some(AS_KW), - "extern" => Some(EXTERN_KW), - "crate" => Some(CRATE_KW), - "mod" => Some(MOD_KW), - "pub" => Some(PUB_KW), - "self" => Some(SELF_KW), - "super" => Some(SUPER_KW), - "in" => Some(IN_KW), - "where" => Some(WHERE_KW), - _ => None, - } + match ident { + "use" => Some(USE_KW), + "fn" => Some(FN_KW), + "struct" => Some(STRUCT_KW), + "enum" => Some(ENUM_KW), + "trait" => Some(TRAIT_KW), + "impl" => Some(IMPL_KW), + "true" => Some(TRUE_KW), + "false" => Some(FALSE_KW), + "as" => Some(AS_KW), + "extern" => Some(EXTERN_KW), + "crate" => Some(CRATE_KW), + "mod" => Some(MOD_KW), + "pub" => Some(PUB_KW), + "self" => Some(SELF_KW), + "super" => Some(SUPER_KW), + "in" => Some(IN_KW), + "where" => Some(WHERE_KW), + _ => None, + } } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index aaf048c73415..43bda480dbe0 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -1,5 +1,4 @@ use text::{TextRange, TextUnit}; -use syntax_kinds::syntax_info; use std::fmt; use std::cmp; @@ -7,25 +6,7 @@ use std::cmp; mod file_builder; pub use self::file_builder::{FileBuilder, Sink}; -/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SyntaxKind(pub(crate) u32); - -pub(crate) const EOF: SyntaxKind = SyntaxKind(!0); -pub(crate) const EOF_INFO: SyntaxInfo = SyntaxInfo { name: "EOF" }; - -pub(crate) const TOMBSTONE: SyntaxKind = SyntaxKind(!0 - 1); -pub(crate) const TOMBSTONE_INFO: SyntaxInfo = SyntaxInfo { name: "TOMBSTONE" }; - -impl SyntaxKind { - fn info(self) -> &'static SyntaxInfo { - match self { - EOF => &EOF_INFO, - TOMBSTONE => &TOMBSTONE_INFO, - _ => syntax_info(self), - } - } -} +pub use syntax_kinds::SyntaxKind; impl fmt::Debug for SyntaxKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {