(&mut self, visibility: Visibility)
| 457 | } |
| 458 | |
| 459 | fn class_declaration(&mut self, visibility: Visibility) -> Option<Stmt<'gc>> { |
| 460 | self.consume_either( |
| 461 | TokenType::Identifier, |
| 462 | TokenType::Error, |
| 463 | "Expect class name.", |
| 464 | ); |
| 465 | let name = self.previous; |
| 466 | if name.is_error_type() && self.match_token(TokenType::OpenParen) { |
| 467 | self.error_at(name, "Error types cannot inherit from other classes."); |
| 468 | return None; |
| 469 | } |
| 470 | |
| 471 | self.scopes.push(name.lexeme.to_owned()); |
| 472 | let superclass = if self.match_token(TokenType::OpenParen) { |
| 473 | self.consume(TokenType::Identifier, "Expect superclass name."); |
| 474 | let superclass_name = self.previous; |
| 475 | if name.lexeme == superclass_name.lexeme { |
| 476 | self.error("A class can't inherit from itself."); |
| 477 | } |
| 478 | self.consume(TokenType::CloseParen, "Expect ')' after superclass name"); |
| 479 | Some(Expr::Variable { |
| 480 | name: superclass_name, |
| 481 | line: superclass_name.line, |
| 482 | }) |
| 483 | } else { |
| 484 | None |
| 485 | }; |
| 486 | |
| 487 | let class_compiler = ClassCompiler { |
| 488 | has_superclass: superclass.is_some(), |
| 489 | is_enum: false, |
| 490 | enclosing: self.class_compiler.take(), |
| 491 | current_method_type: self.fn_type, |
| 492 | }; |
| 493 | self.class_compiler = Some(Box::new(class_compiler)); |
| 494 | |
| 495 | self.type_resolver.register_class(name); |
| 496 | self.consume(TokenType::OpenBrace, "Expect '{' before class body."); |
| 497 | |
| 498 | let mut fields = Vec::new(); |
| 499 | let mut methods = Vec::new(); |
| 500 | while !self.check(TokenType::CloseBrace) && !self.is_at_end() { |
| 501 | let mut validators = Vec::new(); |
| 502 | if self.check(TokenType::At) { |
| 503 | validators = DirectiveParser::new(&mut self.scanner).parse_validators(); |
| 504 | } |
| 505 | if self.check(TokenType::Identifier) && !self.check_next(TokenType::OpenParen) { |
| 506 | let mut field = self.parse_class_field()?; |
| 507 | self.type_resolver.add_class_field( |
| 508 | name.lexeme, |
| 509 | ClassField { |
| 510 | name: field.name, |
| 511 | ty: Type::from_token(field.type_hint), |
| 512 | required: field.default_value.is_none(), |
| 513 | }, |
| 514 | ); |
| 515 | field.validators = validators; |
| 516 | fields.push(field); |
no test coverage detected