1 // Copyright (c) 2019, Facebook, Inc.
2 // All rights reserved.
4 // This source code is licensed under the MIT license found in the
5 // LICENSE file in the "hack" directory of this source tree.
7 use crate::lexable_token::LexableToken;
8 use crate::syntax_kind::SyntaxKind;
9 use crate::token_kind::TokenKind;
12 use std::marker::Sized;
14 use itertools::Either::{Left, Right};
16 pub use crate::syntax_generated::*;
17 pub use crate::syntax_type::*;
19 pub trait SyntaxValueType<T>
23 fn from_syntax(syntax: &SyntaxVariant<T, Self>) -> Self;
24 fn from_values(ndoes: &[&Self]) -> Self;
25 fn from_children(kind: SyntaxKind, offset: usize, nodes: &[&Self]) -> Self;
26 fn from_token(token: &T) -> Self;
28 /// Returns a range [inclusive, exclusive] for the corresponding text if meaningful
29 /// (note: each implementor will either always return Some(range) or always return None).
30 fn text_range(&self) -> Option<(usize, usize)>; // corresponds to extract_text in OCaml impl.
33 pub trait SyntaxValueWithKind
37 fn is_missing(&self) -> bool;
38 fn token_kind(&self) -> Option<TokenKind>;
41 #[derive(Debug, Clone)]
42 pub struct Syntax<T, V> {
43 pub syntax: SyntaxVariant<T, V>,
47 pub trait SyntaxTypeBase<'a, C> {
48 type Token: LexableToken<'a>;
49 type Value: SyntaxValueType<Self::Token>;
51 fn make_missing(ctx: &C, offset: usize) -> Self;
52 fn make_token(ctx: &C, arg: Self::Token) -> Self;
53 fn make_list(ctx: &C, arg: Vec<Self>, offset: usize) -> Self
57 fn value(&self) -> &Self::Value;
60 impl<'a, T, V, C> SyntaxTypeBase<'a, C> for Syntax<T, V>
63 V: SyntaxValueType<T>,
68 fn make_missing(_: &C, offset: usize) -> Self {
69 let value = V::from_children(SyntaxKind::Missing, offset, &[]);
70 let syntax = SyntaxVariant::Missing;
71 Self::make(syntax, value)
74 fn make_token(_: &C, arg: T) -> Self {
78 fn make_list(ctx: &C, arg: Vec<Self>, offset: usize) -> Self {
79 // An empty list is represented by Missing; everything else is a
80 // SyntaxList, even if the list has only one item.
82 Self::make_missing(ctx, offset)
84 // todo: pass iter directly
85 let nodes = &arg.iter().map(|x| &x.value).collect::<Vec<_>>();
86 let value = V::from_children(SyntaxKind::SyntaxList, offset, nodes);
87 let syntax = SyntaxVariant::SyntaxList(arg);
88 Self::make(syntax, value)
92 fn value(&self) -> &Self::Value {
97 impl<'src, T, V> Syntax<T, V>
99 T: LexableToken<'src>,
100 V: SyntaxValueType<T>,
102 pub fn make(syntax: SyntaxVariant<T, V>, value: V) -> Self {
103 Self { syntax, value }
106 pub fn make_token(arg: T) -> Self {
107 let value = V::from_token(&arg);
108 let syntax = SyntaxVariant::Token(Box::new(arg));
109 Self::make(syntax, value)
112 fn is_specific_token(&self, kind: TokenKind) -> bool {
114 SyntaxVariant::Token(t) => t.kind() == kind,
119 pub fn is_public(&self) -> bool {
120 self.is_specific_token(TokenKind::Public)
123 pub fn is_private(&self) -> bool {
124 self.is_specific_token(TokenKind::Private)
127 pub fn is_protected(&self) -> bool {
128 self.is_specific_token(TokenKind::Protected)
131 pub fn is_abstract(&self) -> bool {
132 self.is_specific_token(TokenKind::Abstract)
135 pub fn is_static(&self) -> bool {
136 self.is_specific_token(TokenKind::Static)
139 pub fn is_ampersand(&self) -> bool {
140 self.is_specific_token(TokenKind::Ampersand)
143 pub fn is_ellipsis(&self) -> bool {
144 self.is_specific_token(TokenKind::DotDotDot)
147 pub fn is_final(&self) -> bool {
148 self.is_specific_token(TokenKind::Final)
151 pub fn is_xhp(&self) -> bool {
152 self.is_specific_token(TokenKind::XHP)
155 pub fn is_async(&self) -> bool {
156 self.is_specific_token(TokenKind::Async)
159 pub fn is_yield(&self) -> bool {
160 self.is_specific_token(TokenKind::Yield)
163 pub fn is_construct(&self) -> bool {
164 self.is_specific_token(TokenKind::Construct)
167 pub fn is_void(&self) -> bool {
168 self.is_specific_token(TokenKind::Void)
171 pub fn is_left_brace(&self) -> bool {
172 self.is_specific_token(TokenKind::LeftBrace)
175 pub fn is_comma(&self) -> bool {
176 self.is_specific_token(TokenKind::Comma)
179 pub fn is_inout(&self) -> bool {
180 self.is_specific_token(TokenKind::Inout)
183 pub fn is_this(&self) -> bool {
184 self.is_specific_token(TokenKind::This)
187 pub fn is_name(&self) -> bool {
188 self.is_specific_token(TokenKind::Name)
191 pub fn is_as_expression(&self) -> bool {
192 self.kind() == SyntaxKind::AsExpression
195 pub fn is_missing(&self) -> bool {
196 self.kind() == SyntaxKind::Missing
199 pub fn is_external(&self) -> bool {
200 self.is_specific_token(TokenKind::Semicolon) || self.is_missing()
203 pub fn is_namespace_empty_body(&self) -> bool {
204 self.kind() == SyntaxKind::NamespaceEmptyBody
207 pub fn is_attribute_specification(&self) -> bool {
208 self.kind() == SyntaxKind::AttributeSpecification
211 pub fn is_old_attribute_specification(&self) -> bool {
212 self.kind() == SyntaxKind::OldAttributeSpecification
215 pub fn is_file_attribute_specification(&self) -> bool {
216 self.kind() == SyntaxKind::FileAttributeSpecification
219 pub fn is_return_statement(&self) -> bool {
220 self.kind() == SyntaxKind::ReturnStatement
223 pub fn is_conditional_expression(&self) -> bool {
224 self.kind() == SyntaxKind::ConditionalExpression
227 pub fn is_safe_member_selection_expression(&self) -> bool {
228 self.kind() == SyntaxKind::SafeMemberSelectionExpression
231 pub fn is_object_creation_expression(&self) -> bool {
232 self.kind() == SyntaxKind::ObjectCreationExpression
235 pub fn is_compound_statement(&self) -> bool {
236 self.kind() == SyntaxKind::CompoundStatement
239 pub fn is_methodish_declaration(&self) -> bool {
240 self.kind() == SyntaxKind::MethodishDeclaration
243 pub fn is_function_declaration(&self) -> bool {
244 self.kind() == SyntaxKind::FunctionDeclaration
247 pub fn is_xhp_open(&self) -> bool {
248 self.kind() == SyntaxKind::XHPOpen
251 pub fn is_braced_expression(&self) -> bool {
252 self.kind() == SyntaxKind::BracedExpression
255 pub fn is_syntax_list(&self) -> bool {
256 self.kind() == SyntaxKind::SyntaxList
259 pub fn syntax_node_to_list<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self> {
260 use std::iter::{empty, once};
262 SyntaxVariant::SyntaxList(x) => Left(x.iter()),
263 SyntaxVariant::Missing => Right(Left(empty())),
264 _ => Right(Right(once(self))),
268 pub fn syntax_node_into_list(self) -> impl DoubleEndedIterator<Item = Self> {
269 use std::iter::{empty, once};
271 SyntaxVariant::SyntaxList(x) => Left(x.into_iter()),
272 SyntaxVariant::Missing => Right(Left(empty())),
273 _ => Right(Right(once(self))),
277 pub fn syntax_node_to_list_skip_separator<'a>(
279 ) -> impl DoubleEndedIterator<Item = &'a Self> {
280 use std::iter::{empty, once};
282 SyntaxVariant::SyntaxList(l) => Left(l.iter().map(|n| match &n.syntax {
283 SyntaxVariant::ListItem(i) => &i.list_item,
286 SyntaxVariant::Missing => Right(Left(empty())),
287 _ => Right(Right(once(self))),
291 pub fn is_namespace_prefix(&self) -> bool {
292 if let SyntaxVariant::QualifiedName(x) = &self.syntax {
293 x.qualified_name_parts
294 .syntax_node_to_list()
296 .map_or(false, |p| match &p.syntax {
297 SyntaxVariant::ListItem(x) => !&x.list_separator.is_missing(),
305 pub fn drain_children(&mut self) -> Vec<Self> {
306 let f = |node: Self, mut acc: Vec<Self>| {
310 let syntax = std::mem::replace(&mut self.syntax, SyntaxVariant::Missing);
311 Self::fold_over_children_owned(&f, vec![], syntax)
314 pub fn replace_children(
318 children_changed: bool,
320 if !children_changed {
321 self.syntax = Syntax::from_children(kind, children);
323 let children_values = &children.iter().map(|x| &x.value).collect::<Vec<_>>();
324 let value = V::from_children(kind, 0, children_values);
325 let syntax = Syntax::from_children(kind, children);
326 *self = Self::make(syntax, value);
330 pub fn get_token(&self) -> Option<&T> {
332 SyntaxVariant::Token(t) => Some(&t),
337 pub fn leading_token(&self) -> Option<&T> {
338 match self.get_token() {
339 Some(token) => Some(token),
341 for node in self.iter_children() {
342 if let Some(token) = node.leading_token() {
351 pub fn trailing_token(&self) -> Option<&T> {
352 match self.get_token() {
353 Some(token) => Some(token),
355 for node in self.iter_children().rev() {
356 if let Some(token) = node.trailing_token() {
365 pub fn iter_children<'a>(&'a self) -> SyntaxChildrenIterator<'a, T, V> {
366 self.syntax.iter_children()
369 pub fn all_tokens<'a>(node: &'a Self) -> Vec<&'a T> {
370 Self::all_tokens_with_acc(node, vec![])
373 fn all_tokens_with_acc<'a>(node: &'a Self, mut acc: Vec<&'a T>) -> Vec<&'a T> {
375 SyntaxVariant::Token(t) => acc.push(t),
377 for child in node.iter_children() {
378 acc = Self::all_tokens_with_acc(child, acc)
386 pub struct SyntaxChildrenIterator<'a, T, V> {
387 pub syntax: &'a SyntaxVariant<T, V>,
389 pub index_back: usize,
392 impl<'src, T, V> SyntaxVariant<T, V> {
393 pub fn iter_children<'a>(&'a self) -> SyntaxChildrenIterator<'a, T, V> {
394 SyntaxChildrenIterator {
402 impl<'a, T, V> Iterator for SyntaxChildrenIterator<'a, T, V> {
403 type Item = &'a Syntax<T, V>;
404 fn next(&mut self) -> Option<Self::Item> {
409 impl<'a, T, V> DoubleEndedIterator for SyntaxChildrenIterator<'a, T, V> {
410 fn next_back(&mut self) -> Option<Self::Item> {
411 self.next_impl(false)