Skip to content

Commit 787cfa4

Browse files
committed
Add support for enum cases
1 parent 5eb2ad9 commit 787cfa4

5 files changed

Lines changed: 1474 additions & 3 deletions

File tree

src/completion/resolver.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,17 @@ impl Backend {
559559
return results;
560560
}
561561
}
562+
Statement::Enum(enum_def) => {
563+
let start = enum_def.left_brace.start.offset;
564+
let end = enum_def.right_brace.end.offset;
565+
if ctx.cursor_offset < start || ctx.cursor_offset > end {
566+
continue;
567+
}
568+
let results = Self::resolve_variable_in_members(enum_def.members.iter(), ctx);
569+
if !results.is_empty() {
570+
return results;
571+
}
572+
}
562573
Statement::Namespace(ns) => {
563574
let results = Self::resolve_variable_in_statements(ns.statements().iter(), ctx);
564575
if !results.is_empty() {

src/definition/resolve.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,21 @@ impl Backend {
10371037
});
10381038
}
10391039
}
1040+
// Also look for `case CASE_NAME` (enum cases are stored
1041+
// as constants but declared with `case` keyword).
1042+
let case_pattern = format!("case {}", member_name);
1043+
if let Some(col) = line.find(&case_pattern) {
1044+
let before_ok = col == 0 || is_word_boundary(line.as_bytes()[col - 1]);
1045+
let after_pos = col + case_pattern.len();
1046+
let after_ok =
1047+
after_pos >= line.len() || is_word_boundary(line.as_bytes()[after_pos]);
1048+
if before_ok && after_ok {
1049+
return Some(Position {
1050+
line: line_idx as u32,
1051+
character: col as u32,
1052+
});
1053+
}
1054+
}
10401055
}
10411056
MemberKind::Property => {
10421057
// Look for `$propertyName` on a line that looks like a

src/parser.rs

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,60 @@ impl Backend {
680680
mixins,
681681
});
682682
}
683+
Statement::Enum(enum_def) => {
684+
let enum_name = enum_def.name.value.to_string();
685+
686+
let (mut methods, mut properties, constants, used_traits) =
687+
Self::extract_class_like_members(enum_def.members.iter(), doc_ctx);
688+
689+
// Extract @property, @method, and @mixin tags from the enum-level docblock.
690+
let mut mixins = Vec::new();
691+
if let Some(ctx) = doc_ctx
692+
&& let Some(doc_text) =
693+
docblock::get_docblock_text_for_node(ctx.trivias, ctx.content, enum_def)
694+
{
695+
for (name, type_str) in docblock::extract_property_tags(doc_text) {
696+
if !properties.iter().any(|p| p.name == name) {
697+
properties.push(PropertyInfo {
698+
name,
699+
type_hint: if type_str.is_empty() {
700+
None
701+
} else {
702+
Some(type_str)
703+
},
704+
is_static: false,
705+
visibility: Visibility::Public,
706+
});
707+
}
708+
}
709+
710+
for method_info in docblock::extract_method_tags(doc_text) {
711+
if !methods.iter().any(|m| m.name == method_info.name) {
712+
methods.push(method_info);
713+
}
714+
}
715+
716+
mixins = docblock::extract_mixin_tags(doc_text);
717+
}
718+
719+
// Enums can implement interfaces but cannot extend classes.
720+
let parent_class = None;
721+
722+
let start_offset = enum_def.left_brace.start.offset;
723+
let end_offset = enum_def.right_brace.end.offset;
724+
725+
classes.push(ClassInfo {
726+
name: enum_name,
727+
methods,
728+
properties,
729+
constants,
730+
start_offset,
731+
end_offset,
732+
parent_class,
733+
used_traits,
734+
mixins,
735+
});
736+
}
683737
Statement::Namespace(namespace) => {
684738
Self::extract_classes_from_statements(
685739
namespace.statements().iter(),
@@ -813,12 +867,19 @@ impl Backend {
813867
});
814868
}
815869
}
870+
ClassLikeMember::EnumCase(enum_case) => {
871+
let case_name = enum_case.item.name().value.to_string();
872+
constants.push(ConstantInfo {
873+
name: case_name,
874+
type_hint: None,
875+
visibility: Visibility::Public,
876+
});
877+
}
816878
ClassLikeMember::TraitUse(trait_use) => {
817879
for trait_name_ident in trait_use.trait_names.iter() {
818880
used_traits.push(trait_name_ident.value().to_string());
819881
}
820882
}
821-
_ => {}
822883
}
823884
}
824885

@@ -861,7 +922,10 @@ impl Backend {
861922
Statement::Use(use_stmt) => {
862923
Self::extract_use_items(&use_stmt.items, &mut use_map);
863924
}
864-
Statement::Class(_) | Statement::Interface(_) | Statement::Trait(_) => {
925+
Statement::Class(_)
926+
| Statement::Interface(_)
927+
| Statement::Trait(_)
928+
| Statement::Enum(_) => {
865929
Self::extract_classes_from_statements(
866930
std::iter::once(inner),
867931
&mut classes,
@@ -884,7 +948,10 @@ impl Backend {
884948
}
885949
}
886950
}
887-
Statement::Class(_) | Statement::Interface(_) | Statement::Trait(_) => {
951+
Statement::Class(_)
952+
| Statement::Interface(_)
953+
| Statement::Trait(_)
954+
| Statement::Enum(_) => {
888955
Self::extract_classes_from_statements(
889956
std::iter::once(statement),
890957
&mut classes,

0 commit comments

Comments
 (0)