MCPcopy Create free account
hub / github.com/PHPantom-dev/phpantom_lsp / classify_from_tokens

Function classify_from_tokens

src/completion/phpdoc/context.rs:431–524  ·  view source on GitHub ↗

Classify the PHP symbol from the first meaningful tokens.

(text: &str)

Source from the content-addressed store, hash-verified

429
430/// Classify the PHP symbol from the first meaningful tokens.
431fn classify_from_tokens(text: &str) -> DocblockContext {
432 // Track whether a blank line appears before the first code line.
433 // Inline `@var` annotations must be on the line immediately before
434 // the variable assignment — a blank line in between means the
435 // docblock is not attached to the assignment.
436 //
437 // The text starts right after `*/`, so the very first line is the
438 // remainder of the closing `*/` line (typically empty or whitespace).
439 // That first line is NOT a real blank gap — only subsequent empty
440 // lines count.
441 let mut saw_blank_line = false;
442 let mut first_code_line: Option<&str> = None;
443 let mut tokens = Vec::new();
444 let mut skipped_first_line = false;
445 for line in text.lines() {
446 let trimmed = line.trim();
447 if trimmed.is_empty() {
448 if !skipped_first_line {
449 // The tail of the `*/` line — always skip it.
450 skipped_first_line = true;
451 } else if tokens.is_empty() {
452 // A real blank line before any code.
453 saw_blank_line = true;
454 }
455 continue;
456 }
457 skipped_first_line = true;
458 if trimmed.starts_with('*') || trimmed.starts_with("/**") {
459 continue;
460 }
461 if first_code_line.is_none() {
462 first_code_line = Some(trimmed);
463 }
464 for word in trimmed.split_whitespace() {
465 // Store original casing so that uppercase-initial class names
466 // (e.g. `Collection`) are recognised as type hints later.
467 tokens.push(word.to_string());
468 if tokens.len() >= 6 {
469 break;
470 }
471 }
472 if tokens.len() >= 6 {
473 break;
474 }
475 }
476
477 if tokens.is_empty() {
478 return DocblockContext::Unknown;
479 }
480
481 let mut saw_modifier = false;
482 for token in &tokens {
483 let t = token.as_str();
484 let lower = t.to_ascii_lowercase();
485 match lower.as_str() {
486 "function" => return DocblockContext::FunctionOrMethod,
487 "class" | "interface" | "trait" | "enum" => return DocblockContext::ClassLike,
488 "const" => return DocblockContext::Constant,

Callers 1

detect_contextFunction · 0.85

Calls 6

is_variable_assignmentFunction · 0.85
is_type_keywordFunction · 0.85
pushMethod · 0.80
as_strMethod · 0.80
nextMethod · 0.80
is_emptyMethod · 0.45

Tested by

no test coverage detected