1use std::{
2 collections::{hash_map::Entry, VecDeque},
3 convert::TryInto,
4 iter::FusedIterator,
5};
6
7use arrayvec::ArrayVec;
8use derive_more::From;
9use rowan::{NodeOrToken, SyntaxElementChildren, TextSize};
10
11use lang_util::{
12 located::{HasFileNumber, Resolver},
13 position::NodeSpan,
14 FileId,
15};
16
17use crate::{
18 parser::{self, Ast, PreprocessorLang, SyntaxKind::*, SyntaxNode, SyntaxToken},
19 types::path::ParsedPath,
20 util::{LineMap, Unescaped},
21};
22
23use super::{
24 definition::{Definition, MacroInvocation},
25 event::{ErrorKind, Event, ProcessingErrorKind},
26 nodes::{
27 Define, Directive, DirectiveResult, Elif, Else, Empty, EndIf, Error as ErrorDirective,
28 Extension, If, IfDef, IfNDef, Include, Invalid, Line, ParsedLine, Pragma, Undef, Version,
29 },
30 IncludeMode, ProcessorState,
31};
32
33mod if_stack;
34use if_stack::IfStack;
35
36pub struct ExpandLocation {
37 current_file: FileId,
38 line_map: LineMap,
39 line_override: Option<(u32, ParsedLine)>,
40}
41
42impl Resolver for ExpandLocation {
43 fn resolve(&self, offset: TextSize) -> (u32, u32) {
44 self.offset_to_line_and_col(offset)
45 }
46}
47
48impl HasFileNumber for ExpandLocation {
49 fn current_file(&self) -> FileId {
50 self.current_file
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum LocationString<'p> {
56 Number(u32),
57 String(&'p str),
58}
59
60impl LocationString<'_> {
61 pub fn is_number(&self) -> bool {
62 matches!(self, Self::Number(_))
63 }
64}
65
66impl std::fmt::Display for LocationString<'_> {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 match self {
69 LocationString::Number(num) => write!(f, "{}", num),
70 LocationString::String(path) => write!(f, "{}", path),
71 }
72 }
73}
74
75impl ExpandLocation {
76 pub fn new(current_file: FileId) -> Self {
77 Self {
78 current_file,
79 line_map: Default::default(),
80 line_override: Default::default(),
81 }
82 }
83
84 pub fn current_file(&self) -> FileId {
85 self.current_file
86 }
87
88 pub fn line_override(&self) -> Option<&(u32, ParsedLine)> {
89 self.line_override.as_ref()
90 }
91
92 pub fn offset_to_raw_line_and_col(&self, offset: TextSize) -> (u32, u32) {
93 self.line_map.get_line_and_col(offset.into())
94 }
95
96 pub fn offset_to_line_and_col(&self, offset: TextSize) -> (u32, u32) {
97 let line_and_col = self.offset_to_raw_line_and_col(offset);
98 (self.line_to_line_number(line_and_col.0), line_and_col.1)
99 }
100
101 pub fn line_to_line_number(&self, raw_line: u32) -> u32 {
102 if let Some((origin, line_override)) = &self.line_override {
103 let offset = line_override.line_number() as i64 - *origin as i64 - 2;
104 (raw_line as i64 + offset) as u32
105 } else {
106 raw_line
107 }
108 }
109
110 pub fn add_override(&mut self, current_offset: TextSize, line: ParsedLine) {
111 let raw_line = self.line_map.get_line_and_col(current_offset.into()).0;
112
113 self.line_override = match self.line_override.take() {
115 Some((_, prev_override)) => match line {
116 ParsedLine::Line(line_number) => Some(match prev_override {
117 ParsedLine::Line(_) => line,
118 ParsedLine::LineAndFileNumber(_, file_number) => {
119 ParsedLine::LineAndFileNumber(line_number, file_number)
120 }
121 ParsedLine::LineAndPath(_, path) => ParsedLine::LineAndPath(line_number, path),
122 }),
123 ParsedLine::LineAndFileNumber(_, _) | ParsedLine::LineAndPath(_, _) => Some(line),
124 },
125 None => Some(line),
126 }
127 .map(|ov| (raw_line, ov));
128 }
129
130 pub fn string(&self) -> LocationString {
131 if let Some(line_override) = &self.line_override {
132 match &line_override.1 {
133 ParsedLine::LineAndFileNumber(_, number) => {
134 return LocationString::Number(*number);
135 }
136 ParsedLine::LineAndPath(_, path) => {
137 return LocationString::String(path.as_str());
138 }
139 _ => {}
140 }
141 }
142
143 LocationString::Number(self.current_file.number())
144 }
145}
146
147pub(crate) struct ExpandOne {
148 if_stack: IfStack,
149 location: ExpandLocation,
150 state: ExpandState,
151}
152
153#[allow(clippy::large_enum_variant)]
154enum ExpandState {
155 Init {
156 ast: Ast,
157 current_state: ProcessorState,
158 },
159 Iterate {
160 iterator: SyntaxElementChildren<PreprocessorLang>,
161 errors: Vec<parser::Error>,
162 current_state: ProcessorState,
163 },
164 EnterNewFile {
165 iterator: SyntaxElementChildren<PreprocessorLang>,
166 errors: Vec<parser::Error>,
167 current_state: ProcessorState,
168 path: ParsedPath,
169 node: SyntaxNode,
170 },
171 PendingOne {
172 iterator: SyntaxElementChildren<PreprocessorLang>,
173 errors: Vec<parser::Error>,
174 node_or_token: NodeOrToken<SyntaxNode, SyntaxToken>,
175 current_state: ProcessorState,
176 },
177 PendingEvents {
178 iterator: SyntaxElementChildren<PreprocessorLang>,
179 errors: Vec<parser::Error>,
180 events: ArrayVec<Event, 3>,
181 current_state: ProcessorState,
182 },
183 ExpandedTokens {
184 iterator: SyntaxElementChildren<PreprocessorLang>,
185 errors: Vec<parser::Error>,
186 events: VecDeque<Event>,
187 current_state: ProcessorState,
188 },
189 Complete,
190}
191
192#[derive(From)]
193enum HandleNodeResult {
194 Event(Event),
195 EnterFile(Event, SyntaxNode, ParsedPath),
196}
197
198impl ExpandOne {
199 pub fn new(parsed_file: impl Into<(FileId, Ast)>, current_state: ProcessorState) -> Self {
200 let (file_id, ast) = parsed_file.into();
201
202 Self {
203 if_stack: IfStack::new(),
204 location: ExpandLocation::new(file_id),
205 state: ExpandState::Init { ast, current_state },
206 }
207 }
208
209 pub fn state(&self) -> Option<&ProcessorState> {
210 match &self.state {
211 ExpandState::Init { current_state, .. }
212 | ExpandState::Iterate { current_state, .. }
213 | ExpandState::EnterNewFile { current_state, .. }
214 | ExpandState::PendingOne { current_state, .. }
215 | ExpandState::PendingEvents { current_state, .. }
216 | ExpandState::ExpandedTokens { current_state, .. } => Some(current_state),
217 ExpandState::Complete => None,
218 }
219 }
220
221 pub fn set_state(&mut self, new_state: ProcessorState) {
222 match &mut self.state {
223 ExpandState::Init { current_state, .. }
224 | ExpandState::Iterate { current_state, .. }
225 | ExpandState::EnterNewFile { current_state, .. }
226 | ExpandState::PendingOne { current_state, .. }
227 | ExpandState::PendingEvents { current_state, .. }
228 | ExpandState::ExpandedTokens { current_state, .. } => {
229 *current_state = new_state;
230 }
231 ExpandState::Complete => {
232 panic!("cannot update the state on a completed expand");
233 }
234 }
235 }
236
237 pub fn location(&self) -> &ExpandLocation {
238 &self.location
239 }
240
241 fn handle_node(
242 &mut self,
243 current_state: &mut ProcessorState,
244 node: SyntaxNode,
245 ) -> HandleNodeResult {
246 match node.kind() {
247 PP_EMPTY => Event::directive(
248 Directive::new(self.location.current_file(), node, Empty),
249 !self.if_stack.active(),
250 ),
251 PP_VERSION => {
252 let active = self.if_stack.active();
253 let directive: DirectiveResult<Version> =
254 (self.location.current_file(), node).try_into();
255
256 match directive {
257 Ok(directive) => {
258 if active {
260 current_state.version = *directive;
261 }
262
263 Event::directive(directive, !active)
264 }
265 Err(error) => Event::directive_error(error, &self.location, !active),
266 }
267 }
268 PP_EXTENSION => {
269 let active = self.if_stack.active();
270 let directive: DirectiveResult<Extension> =
271 (self.location.current_file(), node).try_into();
272
273 match directive {
274 Ok(directive) => {
275 if active {
276 current_state.extension(&directive);
277 }
278
279 Event::directive(directive, !active)
280 }
281 Err(error) => Event::directive_error(error, &self.location, !active),
282 }
283 }
284 PP_DEFINE => {
285 let active = self.if_stack.active();
286 let directive: DirectiveResult<Define> =
287 (self.location.current_file(), node).try_into();
288
289 match directive {
290 Ok(define) => {
291 let error = if active {
292 if define.name().starts_with("GL_") {
293 Some(ProcessingErrorKind::ProtectedDefine {
294 ident: define.name().into(),
295 is_undef: false,
296 })
297 } else {
298 let definition = Definition::Regular(
299 (*define).clone().into(),
300 self.location.current_file(),
301 );
302
303 match current_state.definitions.entry(define.name().into()) {
304 Entry::Occupied(mut entry) => {
305 if entry.get().protected() {
306 Some(ProcessingErrorKind::ProtectedDefine {
307 ident: define.name().into(),
308 is_undef: false,
309 })
310 } else {
311 *entry.get_mut() = definition;
313
314 None
315 }
316 }
317 Entry::Vacant(entry) => {
318 entry.insert(definition);
319 None
320 }
321 }
322 }
323 } else {
324 None
325 };
326
327 Event::directive_errors(define, !active, error, &self.location)
328 }
329 Err(error) => Event::directive_error(error, &self.location, !active),
330 }
331 }
332 PP_IFDEF => {
333 let active = self.if_stack.active();
334 let directive: DirectiveResult<IfDef> =
335 (self.location.current_file(), node).try_into();
336
337 let (result, ret) = match directive {
338 Ok(ifdef) => {
339 let is_defined = current_state.definitions.contains_key(&ifdef.ident);
340 (is_defined, Event::directive(ifdef, !active))
341 }
342 Err(error) => (true, Event::directive_error(error, &self.location, !active)),
343 };
344
345 self.if_stack.on_if_like(result);
346 ret
347 }
348 PP_IFNDEF => {
349 let active = self.if_stack.active();
350 let directive: DirectiveResult<IfNDef> =
351 (self.location.current_file(), node).try_into();
352
353 let (result, ret) = match directive {
354 Ok(ifndef) => {
355 let is_defined = current_state.definitions.contains_key(&ifndef.ident);
357 (!is_defined, Event::directive(ifndef, !active))
358 }
359 Err((error, node)) => (
360 true,
361 Event::directive_error(
362 (ProcessingErrorKind::DirectiveIfNDef(error), node),
363 &self.location,
364 !active,
365 ),
366 ),
367 };
368
369 self.if_stack.on_if_like(result);
370 ret
371 }
372 PP_IF => {
373 let active = self.if_stack.active();
374 let directive: DirectiveResult<If> =
375 (self.location.current_file(), node).try_into();
376
377 let (result, ret) = match directive {
378 Ok(if_) => {
379 let (value, error) = if active {
380 if_.eval(current_state, &self.location)
381 } else {
382 (true, None)
383 };
384
385 (
386 value,
387 Event::directive_errors(
388 if_,
389 !active,
390 error.map(ProcessingErrorKind::DirectiveIf),
391 &self.location,
392 ),
393 )
394 }
395 Err(error) => (true, Event::directive_error(error, &self.location, !active)),
396 };
397
398 self.if_stack.on_if_like(result);
399 ret
400 }
401 PP_ELIF => {
402 let active = self.if_stack.if_group_active();
403 let directive: DirectiveResult<Elif> =
404 (self.location.current_file(), node).try_into();
405 let mut errors: ArrayVec<_, 2> = ArrayVec::new();
406
407 let expr = match &directive {
408 Ok(elif_) => {
409 if self.if_stack.if_group_active() {
410 let (value, error) = if active {
411 elif_.eval(current_state, &self.location)
412 } else {
413 (true, None)
414 };
415
416 if let Some(error) = error {
417 errors.push(ProcessingErrorKind::DirectiveElif(error));
418 }
419
420 if !self.if_stack.none() {
421 false
423 } else {
424 value
425 }
426 } else {
427 true
429 }
430 }
431 Err(_) => true,
432 };
433
434 if let Err(error) = self.if_stack.on_elif(expr) {
436 errors.push(ProcessingErrorKind::from(error));
437 }
438
439 match directive {
440 Ok(elif_) => Event::directive_errors(elif_, !active, errors, &self.location),
441 Err(error) => Event::directive_error(error, &self.location, !active),
442 }
443 }
444 PP_ELSE => {
445 let active = self.if_stack.if_group_active();
446 let directive: DirectiveResult<Else> =
447 (self.location.current_file(), node).try_into();
448
449 let error = self.if_stack.on_else().err().map(ProcessingErrorKind::from);
451
452 match directive {
453 Ok(else_) => Event::directive_errors(else_, !active, error, &self.location),
454 Err(error) => Event::directive_error(error, &self.location, !active),
455 }
456 }
457 PP_ENDIF => {
458 let active = self.if_stack.if_group_active();
459 let directive: DirectiveResult<EndIf> =
460 (self.location.current_file(), node).try_into();
461
462 let error = self
464 .if_stack
465 .on_endif()
466 .err()
467 .map(ProcessingErrorKind::from);
468
469 match directive {
470 Ok(endif) => Event::directive_errors(endif, !active, error, &self.location),
471 Err(error) => Event::directive_error(error, &self.location, !active),
472 }
473 }
474 PP_UNDEF => {
475 let active = self.if_stack.active();
476 let directive: DirectiveResult<Undef> =
477 (self.location.current_file(), node).try_into();
478
479 match directive {
480 Ok(undef) => {
481 let protected_ident = if active {
482 if undef.ident.starts_with("GL_") {
483 Some(undef.ident.clone())
484 } else if let Some(def) = current_state.definitions.get(&undef.ident) {
485 if def.protected() {
486 Some(undef.ident.clone())
487 } else {
488 current_state.definitions.remove(&undef.ident);
489 None
490 }
491 } else {
492 None
493 }
494 } else {
495 None
496 };
497
498 Event::directive_errors(
499 undef,
500 !active,
501 protected_ident.map(|ident| ProcessingErrorKind::ProtectedDefine {
502 ident,
503 is_undef: true,
504 }),
505 &self.location,
506 )
507 }
508 Err((error, node)) => Event::directive_error(
509 (ProcessingErrorKind::DirectiveUndef(error), node),
510 &self.location,
511 !active,
512 ),
513 }
514 }
515 PP_ERROR => {
516 let active = self.if_stack.active();
517 let directive: DirectiveResult<ErrorDirective> =
518 (self.location.current_file(), node).try_into();
519
520 match directive {
521 Ok(error) => {
522 let user_error = ProcessingErrorKind::ErrorDirective {
523 message: error.message.clone(),
524 };
525
526 Event::directive_errors(
527 error,
528 !active,
529 std::iter::once(user_error),
530 &self.location,
531 )
532 }
533 Err(error) => Event::directive_error(error, &self.location, !active),
534 }
535 }
536 PP_INCLUDE => {
537 let active = self.if_stack.active();
538 let directive: DirectiveResult<Include> =
540 (self.location.current_file(), node.clone()).try_into();
541
542 let (directive, path) = match directive {
545 Ok(directive) => match directive.path(current_state, &self.location) {
546 Ok(path) => (Ok(directive), Some(path)),
547 Err(err) => (Err((err, directive.node().clone())), None),
548 },
549 err => (err, None),
550 };
551
552 match directive {
553 Ok(include) => {
554 let error = match (path, current_state.include_mode) {
555 (_, IncludeMode::None) if active => {
556 Some(ErrorKind::Processing(
559 ProcessingErrorKind::IncludeNotSupported,
560 ))
561 }
562 (Some(path), IncludeMode::GoogleInclude { warn }) if active => {
563 let node = include.node().clone();
565 return HandleNodeResult::EnterFile(
566 Event::directive_errors(
567 include,
568 !active,
569 if warn {
570 Some(ErrorKind::warn_ext_use(
571 ext_name!("GL_GOOGLE_include_directive"),
572 None,
573 NodeSpan::new(
574 self.location.current_file(),
575 node.text_range(),
576 ),
577 &self.location,
578 ))
579 } else {
580 None
581 },
582 &self.location,
583 ),
584 node,
585 path,
586 );
587 }
588 (_, other) => {
590 if other.warn() {
591 if matches!(other, IncludeMode::GoogleInclude { .. }) {
592 Some(ErrorKind::warn_ext_use(
593 ext_name!("GL_GOOGLE_include_directive"),
594 None,
595 NodeSpan::new(
596 self.location.current_file(),
597 node.text_range(),
598 ),
599 &self.location,
600 ))
601 } else if matches!(other, IncludeMode::ArbInclude { .. }) {
602 Some(ErrorKind::warn_ext_use(
603 ext_name!("GL_ARB_shading_language_include"),
604 None,
605 NodeSpan::new(
606 self.location.current_file(),
607 node.text_range(),
608 ),
609 &self.location,
610 ))
611 } else {
612 None
613 }
614 } else {
615 None
616 }
617 }
618 };
619
620 Event::directive_errors(include, !active, error, &self.location)
622 }
623 Err(error) => {
624 if current_state.include_mode == IncludeMode::None {
625 Event::directive_error(
628 (ProcessingErrorKind::IncludeNotSupported, node),
629 &self.location,
630 !active,
631 )
632 } else {
633 Event::directive_error(error, &self.location, !active)
634 }
635 }
636 }
637 }
638 PP_LINE => {
639 let active = self.if_stack.active();
640 let directive: DirectiveResult<Line> =
642 (self.location.current_file(), node).try_into();
643
644 let (directive, line) = match directive {
647 Ok(directive) => match directive.parse(current_state, &self.location) {
648 Ok(path) => (Ok(directive), Some(path)),
649 Err(err) => (Err((err, directive.node().clone())), None),
650 },
651 err => (err, None),
652 };
653
654 match directive {
655 Ok(ld) => {
656 let error = if active {
657 if let Some(line) = line {
658 let (line, error) = match line {
660 ParsedLine::Line(_) | ParsedLine::LineAndFileNumber(_, _) => {
661 (line, None)
662 }
663 ParsedLine::LineAndPath(_, _)
664 if current_state.cpp_style_line() =>
665 {
666 (line, None)
667 }
668 ParsedLine::LineAndPath(line, _) => (
669 ParsedLine::Line(line),
670 Some(ProcessingErrorKind::CppStyleLineNotSupported),
671 ),
672 };
673
674 self.location
675 .add_override(ld.node().text_range().start(), line);
676 error
677 } else {
678 None
679 }
680 } else {
681 None
682 };
683
684 Event::directive_errors(ld, !active, error, &self.location)
685 }
686 Err(error) => Event::directive_error(error, &self.location, !active),
687 }
688 }
689 PP_PRAGMA => {
690 let active = self.if_stack.active();
691 let directive: DirectiveResult<Pragma> =
692 (self.location.current_file(), node).try_into();
693
694 match directive {
695 Ok(pragma) => Event::directive(pragma, !active),
696 Err(error) => Event::directive_error(error, &self.location, !active),
697 }
698 }
699 ERROR => {
700 Event::directive(
702 Directive::new(self.location.current_file(), node, Invalid),
703 !self.if_stack.active(),
704 )
705 }
706 _ => {
707 panic!("unhandled node type: {:?}", node.kind());
709 }
710 }
711 .into()
712 }
713
714 fn handle_token(
715 &mut self,
716 current_state: ProcessorState,
717 token: SyntaxToken,
718 iterator: SyntaxElementChildren<PreprocessorLang>,
719 errors: Vec<parser::Error>,
720 ) -> Option<Event> {
721 if let Some(definition) = (if self.if_stack.active() && token.kind() == IDENT_KW {
723 Some(Unescaped::new(token.text()).to_string())
724 } else {
725 None
726 })
727 .and_then(|ident| current_state.definitions.get(ident.as_ref()))
728 {
729 match MacroInvocation::parse_raw(
732 definition,
733 token.clone(),
734 iterator.clone(),
735 &self.location,
736 ) {
737 Ok(Some((invocation, new_iterator))) => {
738 self.state = ExpandState::ExpandedTokens {
740 iterator: new_iterator,
741 errors,
742 events: invocation.substitute(¤t_state, &self.location).into(),
743 current_state,
744 };
745 }
746 Ok(None) => {
747 self.state = ExpandState::Iterate {
750 iterator,
751 errors,
752 current_state,
753 };
754
755 return Some(Event::token((token, self.location.current_file()), false));
756 }
757 Err(err) => {
758 let mut events = ArrayVec::new();
759 let pos = err.pos();
760 events.push(Event::error(err.into_inner(), pos, &self.location, false));
761 events.push(Event::token((token, self.location.current_file()), false));
762
763 self.state = ExpandState::PendingEvents {
764 iterator,
765 errors,
766 events,
767 current_state,
768 };
769 }
770 }
771
772 None
773 } else {
774 self.state = ExpandState::Iterate {
776 iterator,
777 errors,
778 current_state,
779 };
780
781 Some(Event::token(
782 (token, self.location.current_file()),
783 !self.if_stack.active(),
784 ))
785 }
786 }
787
788 fn handle_node_or_token(
789 &mut self,
790 mut current_state: ProcessorState,
791 iterator: SyntaxElementChildren<PreprocessorLang>,
792 errors: Vec<parser::Error>,
793 node_or_token: NodeOrToken<SyntaxNode, SyntaxToken>,
794 ) -> Option<Event> {
795 match node_or_token {
796 rowan::NodeOrToken::Node(node) => match self.handle_node(&mut current_state, node) {
797 HandleNodeResult::Event(event) => {
798 self.state = ExpandState::Iterate {
799 iterator,
800 errors,
801 current_state,
802 };
803
804 Some(event)
805 }
806
807 HandleNodeResult::EnterFile(event, node, path) => {
808 self.state = ExpandState::EnterNewFile {
809 iterator,
810 errors,
811 current_state,
812 path,
813 node,
814 };
815
816 Some(event)
817 }
818 },
819 rowan::NodeOrToken::Token(token) => {
820 self.handle_token(current_state, token, iterator, errors)
821 }
822 }
823 }
824}
825
826pub(crate) enum ExpandEvent {
827 Event(Event),
828 EnterFile(SyntaxNode, ParsedPath),
829 Completed(ProcessorState),
830}
831
832impl From<Event> for ExpandEvent {
833 fn from(event: Event) -> Self {
834 Self::Event(event)
835 }
836}
837
838impl Iterator for ExpandOne {
839 type Item = ExpandEvent;
840
841 fn next(&mut self) -> Option<Self::Item> {
842 loop {
843 match std::mem::replace(&mut self.state, ExpandState::Complete) {
844 ExpandState::Init { ast, current_state } => {
845 let (root, errors, line_map) = ast.into_inner();
846
847 self.location.line_map = line_map;
849
850 self.state = ExpandState::Iterate {
851 iterator: root.children_with_tokens(),
852 errors,
853 current_state,
854 };
855
856 return Some(Event::enter_file(self.location.current_file).into());
857 }
858 ExpandState::Iterate {
859 mut iterator,
860 mut errors,
861 current_state,
862 } => {
863 if let Some(node_or_token) = iterator.next() {
864 if let Some(first) = errors.first() {
865 if node_or_token.text_range().end() >= first.pos().start() {
866 let error = errors.pop().unwrap();
867 let pos = node_or_token.text_range();
868
869 self.state = ExpandState::PendingOne {
870 iterator,
871 errors,
872 node_or_token,
873 current_state,
874 };
875
876 return Some(
877 Event::error(
878 error.into_inner(),
879 pos,
880 &self.location,
881 !self.if_stack.active(),
882 )
883 .into(),
884 );
885 }
886 }
887
888 if let Some(result) = self.handle_node_or_token(
889 current_state,
890 iterator,
891 errors,
892 node_or_token,
893 ) {
894 return Some(result.into());
895 }
896 } else {
897 return Some(ExpandEvent::Completed(current_state));
899 }
900 }
901
902 ExpandState::EnterNewFile {
903 iterator,
904 errors,
905 current_state,
906 path,
907 node,
908 } => {
909 self.state = ExpandState::Iterate {
910 iterator,
911 errors,
912 current_state,
913 };
914
915 return Some(ExpandEvent::EnterFile(node, path));
916 }
917
918 ExpandState::PendingOne {
919 iterator,
920 errors,
921 node_or_token,
922 current_state,
923 } => {
924 if let Some(result) =
925 self.handle_node_or_token(current_state, iterator, errors, node_or_token)
926 {
927 return Some(result.into());
928 }
929 }
930 ExpandState::PendingEvents {
931 iterator,
932 errors,
933 mut events,
934 current_state,
935 } => {
936 if let Some(event) = events.swap_pop(0) {
937 self.state = ExpandState::PendingEvents {
938 iterator,
939 errors,
940 events,
941 current_state,
942 };
943
944 return Some(event.into());
945 } else {
946 self.state = ExpandState::Iterate {
947 iterator,
948 errors,
949 current_state,
950 };
951 }
952 }
953
954 ExpandState::ExpandedTokens {
955 iterator,
956 errors,
957 mut events,
958 current_state,
959 } => {
960 if let Some(event) = events.pop_front() {
961 self.state = ExpandState::ExpandedTokens {
962 iterator,
963 errors,
964 events,
965 current_state,
966 };
967
968 return Some(event.into());
969 } else {
970 self.state = ExpandState::Iterate {
971 iterator,
972 errors,
973 current_state,
974 };
975 }
976 }
977
978 ExpandState::Complete => {
979 return None;
980 }
981 }
982 }
983 }
984}
985
986impl FusedIterator for ExpandOne {}