()
| 601 | } |
| 602 | |
| 603 | func (p *Parser) parseField() *FieldNode { |
| 604 | // Skip annotations |
| 605 | for p.peek().Value == "@" { |
| 606 | p.next() // @ |
| 607 | p.next() // Name |
| 608 | if p.peek().Value == "(" { |
| 609 | p.next() |
| 610 | p.skipBalanced("(", ")") |
| 611 | } |
| 612 | } |
| 613 | |
| 614 | // Skip modifiers |
| 615 | modifiers := []string{"public", "private", "protected", "static", "final", "transient", "volatile"} |
| 616 | for contains(modifiers, p.peek().Value) { |
| 617 | p.next() |
| 618 | } |
| 619 | |
| 620 | // Type |
| 621 | typeStr := p.next().Value |
| 622 | // Handle generics |
| 623 | if p.peek().Value == "<" { |
| 624 | p.next() |
| 625 | gen := p.consumeBalanced("<", ">") |
| 626 | typeStr += "<" + gen + ">" |
| 627 | } |
| 628 | |
| 629 | // Name |
| 630 | nameStr := p.next().Value |
| 631 | |
| 632 | // Skip until ; (but respect braces/parens) |
| 633 | braceCount := 0 |
| 634 | parenCount := 0 |
| 635 | for p.pos < len(p.tokens) { |
| 636 | t := p.peek() |
| 637 | if t.Value == ";" && braceCount == 0 && parenCount == 0 { |
| 638 | break |
| 639 | } |
| 640 | if t.Value == "{" { |
| 641 | braceCount++ |
| 642 | } else if t.Value == "}" { |
| 643 | braceCount-- |
| 644 | } else if t.Value == "(" { |
| 645 | parenCount++ |
| 646 | } else if t.Value == ")" { |
| 647 | parenCount-- |
| 648 | } |
| 649 | p.next() |
| 650 | } |
| 651 | p.consume(";") |
| 652 | |
| 653 | return &FieldNode{ |
| 654 | Name: nameStr, |
| 655 | Type: typeStr, |
| 656 | } |
| 657 | } |
| 658 | |
| 659 | func (p *Parser) skipBalanced(open, close string) { |
| 660 | count := 1 |
no test coverage detected