Classify the PHP symbol from the first meaningful tokens after the trigger.
(text: &str)
| 507 | /// Classify the PHP symbol from the first meaningful tokens after the |
| 508 | /// trigger. |
| 509 | fn classify_declaration(text: &str) -> DocblockContext { |
| 510 | let mut tokens = Vec::new(); |
| 511 | let mut attr_depth = 0i32; |
| 512 | for line in text.lines() { |
| 513 | let trimmed = line.trim(); |
| 514 | if trimmed.is_empty() { |
| 515 | continue; |
| 516 | } |
| 517 | // Skip lines that look like docblock continuation (shouldn't |
| 518 | // happen after our trigger, but be safe). |
| 519 | if trimmed.starts_with('*') || trimmed.starts_with("/**") { |
| 520 | continue; |
| 521 | } |
| 522 | // Skip PHP 8 attribute lines (#[...]). Track bracket nesting |
| 523 | // depth so that array literals inside attributes (e.g. |
| 524 | // `#[Route(methods: ['GET'])]`) don't prematurely end tracking. |
| 525 | if attr_depth > 0 || trimmed.starts_with("#[") { |
| 526 | for ch in trimmed.chars() { |
| 527 | match ch { |
| 528 | '[' => attr_depth += 1, |
| 529 | ']' => attr_depth -= 1, |
| 530 | _ => {} |
| 531 | } |
| 532 | } |
| 533 | continue; |
| 534 | } |
| 535 | for word in trimmed.split_whitespace() { |
| 536 | tokens.push(word.to_lowercase()); |
| 537 | if tokens.len() >= 8 { |
| 538 | break; |
| 539 | } |
| 540 | } |
| 541 | if tokens.len() >= 8 { |
| 542 | break; |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | if tokens.is_empty() { |
| 547 | return DocblockContext::Unknown; |
| 548 | } |
| 549 | |
| 550 | let mut saw_modifier = false; |
| 551 | for token in &tokens { |
| 552 | let t = token.as_str(); |
| 553 | match t { |
| 554 | "function" => return DocblockContext::FunctionOrMethod, |
| 555 | "class" | "interface" | "trait" | "enum" | "abstract" | "final" | "readonly" => { |
| 556 | // "abstract" and "final" could precede either a class or |
| 557 | // a method. Keep scanning. |
| 558 | if matches!(t, "class" | "interface" | "trait" | "enum") { |
| 559 | return DocblockContext::ClassLike; |
| 560 | } |
| 561 | saw_modifier = true; |
| 562 | } |
| 563 | "public" | "protected" | "private" | "static" | "var" => { |
| 564 | saw_modifier = true; |
| 565 | } |
| 566 | "const" => return DocblockContext::Constant, |