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 value
421 } else {
422 true
424 }
425 }
426 Err(_) => true,
427 };
428
429 if let Err(error) = self.if_stack.on_elif(expr) {
431 errors.push(ProcessingErrorKind::from(error));
432 }
433
434 match directive {
435 Ok(elif_) => Event::directive_errors(elif_, !active, errors, &self.location),
436 Err(error) => Event::directive_error(error, &self.location, !active),
437 }
438 }
439 PP_ELSE => {
440 let active = self.if_stack.if_group_active();
441 let directive: DirectiveResult<Else> =
442 (self.location.current_file(), node).try_into();
443
444 let error = self.if_stack.on_else().err().map(ProcessingErrorKind::from);
446
447 match directive {
448 Ok(else_) => Event::directive_errors(else_, !active, error, &self.location),
449 Err(error) => Event::directive_error(error, &self.location, !active),
450 }
451 }
452 PP_ENDIF => {
453 let active = self.if_stack.if_group_active();
454 let directive: DirectiveResult<EndIf> =
455 (self.location.current_file(), node).try_into();
456
457 let error = self
459 .if_stack
460 .on_endif()
461 .err()
462 .map(ProcessingErrorKind::from);
463
464 match directive {
465 Ok(endif) => Event::directive_errors(endif, !active, error, &self.location),
466 Err(error) => Event::directive_error(error, &self.location, !active),
467 }
468 }
469 PP_UNDEF => {
470 let active = self.if_stack.active();
471 let directive: DirectiveResult<Undef> =
472 (self.location.current_file(), node).try_into();
473
474 match directive {
475 Ok(undef) => {
476 let protected_ident = if active {
477 if undef.ident.starts_with("GL_") {
478 Some(undef.ident.clone())
479 } else if let Some(def) = current_state.definitions.get(&undef.ident) {
480 if def.protected() {
481 Some(undef.ident.clone())
482 } else {
483 current_state.definitions.remove(&undef.ident);
484 None
485 }
486 } else {
487 None
488 }
489 } else {
490 None
491 };
492
493 Event::directive_errors(
494 undef,
495 !active,
496 protected_ident.map(|ident| ProcessingErrorKind::ProtectedDefine {
497 ident,
498 is_undef: true,
499 }),
500 &self.location,
501 )
502 }
503 Err((error, node)) => Event::directive_error(
504 (ProcessingErrorKind::DirectiveUndef(error), node),
505 &self.location,
506 !active,
507 ),
508 }
509 }
510 PP_ERROR => {
511 let active = self.if_stack.active();
512 let directive: DirectiveResult<ErrorDirective> =
513 (self.location.current_file(), node).try_into();
514
515 match directive {
516 Ok(error) => {
517 let user_error = ProcessingErrorKind::ErrorDirective {
518 message: error.message.clone(),
519 };
520
521 Event::directive_errors(
522 error,
523 !active,
524 std::iter::once(user_error),
525 &self.location,
526 )
527 }
528 Err(error) => Event::directive_error(error, &self.location, !active),
529 }
530 }
531 PP_INCLUDE => {
532 let active = self.if_stack.active();
533 let directive: DirectiveResult<Include> =
535 (self.location.current_file(), node.clone()).try_into();
536
537 let (directive, path) = match directive {
540 Ok(directive) => match directive.path(current_state, &self.location) {
541 Ok(path) => (Ok(directive), Some(path)),
542 Err(err) => (Err((err, directive.node().clone())), None),
543 },
544 err => (err, None),
545 };
546
547 match directive {
548 Ok(include) => {
549 let error = match (path, current_state.include_mode) {
550 (_, IncludeMode::None) if active => {
551 Some(ErrorKind::Processing(
554 ProcessingErrorKind::IncludeNotSupported,
555 ))
556 }
557 (Some(path), IncludeMode::GoogleInclude { warn }) if active => {
558 let node = include.node().clone();
560 return HandleNodeResult::EnterFile(
561 Event::directive_errors(
562 include,
563 !active,
564 if warn {
565 Some(ErrorKind::warn_ext_use(
566 ext_name!("GL_GOOGLE_include_directive"),
567 None,
568 NodeSpan::new(
569 self.location.current_file(),
570 node.text_range(),
571 ),
572 &self.location,
573 ))
574 } else {
575 None
576 },
577 &self.location,
578 ),
579 node,
580 path,
581 );
582 }
583 (_, other) => {
585 if other.warn() {
586 if matches!(other, IncludeMode::GoogleInclude { .. }) {
587 Some(ErrorKind::warn_ext_use(
588 ext_name!("GL_GOOGLE_include_directive"),
589 None,
590 NodeSpan::new(
591 self.location.current_file(),
592 node.text_range(),
593 ),
594 &self.location,
595 ))
596 } else if matches!(other, IncludeMode::ArbInclude { .. }) {
597 Some(ErrorKind::warn_ext_use(
598 ext_name!("GL_ARB_shading_language_include"),
599 None,
600 NodeSpan::new(
601 self.location.current_file(),
602 node.text_range(),
603 ),
604 &self.location,
605 ))
606 } else {
607 None
608 }
609 } else {
610 None
611 }
612 }
613 };
614
615 Event::directive_errors(include, !active, error, &self.location)
617 }
618 Err(error) => {
619 if current_state.include_mode == IncludeMode::None {
620 Event::directive_error(
623 (ProcessingErrorKind::IncludeNotSupported, node),
624 &self.location,
625 !active,
626 )
627 } else {
628 Event::directive_error(error, &self.location, !active)
629 }
630 }
631 }
632 }
633 PP_LINE => {
634 let active = self.if_stack.active();
635 let directive: DirectiveResult<Line> =
637 (self.location.current_file(), node).try_into();
638
639 let (directive, line) = match directive {
642 Ok(directive) => match directive.parse(current_state, &self.location) {
643 Ok(path) => (Ok(directive), Some(path)),
644 Err(err) => (Err((err, directive.node().clone())), None),
645 },
646 err => (err, None),
647 };
648
649 match directive {
650 Ok(ld) => {
651 let error = if active {
652 if let Some(line) = line {
653 let (line, error) = match line {
655 ParsedLine::Line(_) | ParsedLine::LineAndFileNumber(_, _) => {
656 (line, None)
657 }
658 ParsedLine::LineAndPath(_, _)
659 if current_state.cpp_style_line() =>
660 {
661 (line, None)
662 }
663 ParsedLine::LineAndPath(line, _) => (
664 ParsedLine::Line(line),
665 Some(ProcessingErrorKind::CppStyleLineNotSupported),
666 ),
667 };
668
669 self.location
670 .add_override(ld.node().text_range().start(), line);
671 error
672 } else {
673 None
674 }
675 } else {
676 None
677 };
678
679 Event::directive_errors(ld, !active, error, &self.location)
680 }
681 Err(error) => Event::directive_error(error, &self.location, !active),
682 }
683 }
684 PP_PRAGMA => {
685 let active = self.if_stack.active();
686 let directive: DirectiveResult<Pragma> =
687 (self.location.current_file(), node).try_into();
688
689 match directive {
690 Ok(pragma) => Event::directive(pragma, !active),
691 Err(error) => Event::directive_error(error, &self.location, !active),
692 }
693 }
694 ERROR => {
695 Event::directive(
697 Directive::new(self.location.current_file(), node, Invalid),
698 !self.if_stack.active(),
699 )
700 }
701 _ => {
702 panic!("unhandled node type: {:?}", node.kind());
704 }
705 }
706 .into()
707 }
708
709 fn handle_token(
710 &mut self,
711 current_state: ProcessorState,
712 token: SyntaxToken,
713 iterator: SyntaxElementChildren<PreprocessorLang>,
714 errors: Vec<parser::Error>,
715 ) -> Option<Event> {
716 if let Some(definition) = (if self.if_stack.active() && token.kind() == IDENT_KW {
718 Some(Unescaped::new(token.text()).to_string())
719 } else {
720 None
721 })
722 .and_then(|ident| current_state.definitions.get(ident.as_ref()))
723 {
724 match MacroInvocation::parse_raw(
727 definition,
728 token.clone(),
729 iterator.clone(),
730 &self.location,
731 ) {
732 Ok(Some((invocation, new_iterator))) => {
733 self.state = ExpandState::ExpandedTokens {
735 iterator: new_iterator,
736 errors,
737 events: invocation.substitute(¤t_state, &self.location).into(),
738 current_state,
739 };
740 }
741 Ok(None) => {
742 self.state = ExpandState::Iterate {
745 iterator,
746 errors,
747 current_state,
748 };
749
750 return Some(Event::token((token, self.location.current_file()), false));
751 }
752 Err(err) => {
753 let mut events = ArrayVec::new();
754 let pos = err.pos();
755 events.push(Event::error(err.into_inner(), pos, &self.location, false));
756 events.push(Event::token((token, self.location.current_file()), false));
757
758 self.state = ExpandState::PendingEvents {
759 iterator,
760 errors,
761 events,
762 current_state,
763 };
764 }
765 }
766
767 None
768 } else {
769 self.state = ExpandState::Iterate {
771 iterator,
772 errors,
773 current_state,
774 };
775
776 Some(Event::token(
777 (token, self.location.current_file()),
778 !self.if_stack.active(),
779 ))
780 }
781 }
782
783 fn handle_node_or_token(
784 &mut self,
785 mut current_state: ProcessorState,
786 iterator: SyntaxElementChildren<PreprocessorLang>,
787 errors: Vec<parser::Error>,
788 node_or_token: NodeOrToken<SyntaxNode, SyntaxToken>,
789 ) -> Option<Event> {
790 match node_or_token {
791 rowan::NodeOrToken::Node(node) => match self.handle_node(&mut current_state, node) {
792 HandleNodeResult::Event(event) => {
793 self.state = ExpandState::Iterate {
794 iterator,
795 errors,
796 current_state,
797 };
798
799 Some(event)
800 }
801
802 HandleNodeResult::EnterFile(event, node, path) => {
803 self.state = ExpandState::EnterNewFile {
804 iterator,
805 errors,
806 current_state,
807 path,
808 node,
809 };
810
811 Some(event)
812 }
813 },
814 rowan::NodeOrToken::Token(token) => {
815 self.handle_token(current_state, token, iterator, errors)
816 }
817 }
818 }
819}
820
821pub(crate) enum ExpandEvent {
822 Event(Event),
823 EnterFile(SyntaxNode, ParsedPath),
824 Completed(ProcessorState),
825}
826
827impl From<Event> for ExpandEvent {
828 fn from(event: Event) -> Self {
829 Self::Event(event)
830 }
831}
832
833impl Iterator for ExpandOne {
834 type Item = ExpandEvent;
835
836 fn next(&mut self) -> Option<Self::Item> {
837 loop {
838 match std::mem::replace(&mut self.state, ExpandState::Complete) {
839 ExpandState::Init { ast, current_state } => {
840 let (root, errors, line_map) = ast.into_inner();
841
842 self.location.line_map = line_map;
844
845 self.state = ExpandState::Iterate {
846 iterator: root.children_with_tokens(),
847 errors,
848 current_state,
849 };
850
851 return Some(Event::enter_file(self.location.current_file).into());
852 }
853 ExpandState::Iterate {
854 mut iterator,
855 mut errors,
856 current_state,
857 } => {
858 if let Some(node_or_token) = iterator.next() {
859 if let Some(first) = errors.first() {
860 if node_or_token.text_range().end() >= first.pos().start() {
861 let error = errors.pop().unwrap();
862 let pos = node_or_token.text_range();
863
864 self.state = ExpandState::PendingOne {
865 iterator,
866 errors,
867 node_or_token,
868 current_state,
869 };
870
871 return Some(
872 Event::error(
873 error.into_inner(),
874 pos,
875 &self.location,
876 !self.if_stack.active(),
877 )
878 .into(),
879 );
880 }
881 }
882
883 if let Some(result) = self.handle_node_or_token(
884 current_state,
885 iterator,
886 errors,
887 node_or_token,
888 ) {
889 return Some(result.into());
890 }
891 } else {
892 return Some(ExpandEvent::Completed(current_state));
894 }
895 }
896
897 ExpandState::EnterNewFile {
898 iterator,
899 errors,
900 current_state,
901 path,
902 node,
903 } => {
904 self.state = ExpandState::Iterate {
905 iterator,
906 errors,
907 current_state,
908 };
909
910 return Some(ExpandEvent::EnterFile(node, path));
911 }
912
913 ExpandState::PendingOne {
914 iterator,
915 errors,
916 node_or_token,
917 current_state,
918 } => {
919 if let Some(result) =
920 self.handle_node_or_token(current_state, iterator, errors, node_or_token)
921 {
922 return Some(result.into());
923 }
924 }
925 ExpandState::PendingEvents {
926 iterator,
927 errors,
928 mut events,
929 current_state,
930 } => {
931 if let Some(event) = events.swap_pop(0) {
932 self.state = ExpandState::PendingEvents {
933 iterator,
934 errors,
935 events,
936 current_state,
937 };
938
939 return Some(event.into());
940 } else {
941 self.state = ExpandState::Iterate {
942 iterator,
943 errors,
944 current_state,
945 };
946 }
947 }
948
949 ExpandState::ExpandedTokens {
950 iterator,
951 errors,
952 mut events,
953 current_state,
954 } => {
955 if let Some(event) = events.pop_front() {
956 self.state = ExpandState::ExpandedTokens {
957 iterator,
958 errors,
959 events,
960 current_state,
961 };
962
963 return Some(event.into());
964 } else {
965 self.state = ExpandState::Iterate {
966 iterator,
967 errors,
968 current_state,
969 };
970 }
971 }
972
973 ExpandState::Complete => {
974 return None;
975 }
976 }
977 }
978 }
979}
980
981impl FusedIterator for ExpandOne {}