Skip to content

Commit f725533

Browse files
committed
Strip out hover support
1 parent ec58614 commit f725533

3 files changed

Lines changed: 63 additions & 198 deletions

File tree

example.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,48 @@
11
<?php
22

3+
/**
4+
* PHPantomLSP Demo File
5+
*
6+
* This file demonstrates the hover functionality of PHPantomLSP.
7+
* Try hovering over the word "PHPantom" below to see the special message!
8+
*/
9+
310
namespace Demo;
411

512
class PHPantomDemo
613
{
7-
public int $count = 0;
14+
/**
15+
* Welcome to PHPantom - the phantom PHP Language Server!
16+
*
17+
* Hover over "PHPantom" anywhere in this file to see the LSP in action.
18+
*/
19+
public function demonstrateHover(): void
20+
{
21+
// PHPantom provides basic LSP functionality
22+
$message = "PHPantom is a minimal LSP server written in Rust";
23+
24+
echo $message . PHP_EOL;
25+
}
826

9-
public function regularCode(string $text): string
27+
/**
28+
* Regular PHP code - hovering over these words won't trigger special behavior
29+
*/
30+
public function regularCode(): string
1031
{
32+
$variable = "This is regular code";
33+
$function = "Some function";
34+
35+
// Only "PHPantom" triggers the hover message
36+
return "PHPantom rocks!";
1137
}
1238
}
1339

40+
// Create an instance and run the demo
41+
$demo = new PHPantomDemo();
42+
$demo->demonstrateHover();
43+
44+
// More PHPantom references for testing
45+
// Try hovering over PHPantom in comments too!
46+
$phantom = "PHPantom";
47+
48+
?>

src/lib.rs

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -116,42 +116,6 @@ impl Backend {
116116
}
117117
}
118118

119-
fn get_word_at_position(&self, content: &str, position: Position) -> Option<String> {
120-
let lines: Vec<&str> = content.lines().collect();
121-
if position.line as usize >= lines.len() {
122-
return None;
123-
}
124-
125-
let line = lines[position.line as usize];
126-
let chars: Vec<char> = line.chars().collect();
127-
128-
if position.character as usize > chars.len() {
129-
return None;
130-
}
131-
132-
let pos = position.character as usize;
133-
134-
// Find word boundaries
135-
let mut start = pos;
136-
let mut end = pos;
137-
138-
// Move start backward to word boundary
139-
while start > 0 && chars[start - 1].is_alphanumeric() {
140-
start -= 1;
141-
}
142-
143-
// Move end forward to word boundary
144-
while end < chars.len() && chars[end].is_alphanumeric() {
145-
end += 1;
146-
}
147-
148-
if start < end {
149-
Some(chars[start..end].iter().collect())
150-
} else {
151-
None
152-
}
153-
}
154-
155119
/// Extract a string representation of a type hint from the AST.
156120
fn extract_hint_string(hint: &Hint) -> String {
157121
match hint {
@@ -453,7 +417,6 @@ impl LanguageServer for Backend {
453417
async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> {
454418
Ok(InitializeResult {
455419
capabilities: ServerCapabilities {
456-
hover_provider: Some(HoverProviderCapability::Simple(true)),
457420
completion_provider: Some(CompletionOptions {
458421
resolve_provider: Some(false),
459422
trigger_characters: Some(vec![
@@ -535,35 +498,6 @@ impl LanguageServer for Backend {
535498
.await;
536499
}
537500

538-
async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
539-
let uri = params
540-
.text_document_position_params
541-
.text_document
542-
.uri
543-
.to_string();
544-
let position = params.text_document_position_params.position;
545-
546-
let content = if let Ok(files) = self.open_files.lock() {
547-
files.get(&uri).cloned()
548-
} else {
549-
None
550-
};
551-
552-
if let Some(content) = content
553-
&& let Some(word) = self.get_word_at_position(&content, position)
554-
&& word == "PHPantom"
555-
{
556-
return Ok(Some(Hover {
557-
contents: HoverContents::Scalar(MarkedString::String(
558-
"Welcome to PHPantomLSP!".to_string(),
559-
)),
560-
range: None,
561-
}));
562-
}
563-
564-
Ok(None)
565-
}
566-
567501
async fn completion(&self, params: CompletionParams) -> Result<Option<CompletionResponse>> {
568502
let uri = params.text_document_position.text_document.uri.to_string();
569503
let position = params.text_document_position.position;

tests/integration_tests.rs

Lines changed: 26 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ async fn test_initialize_capabilities() {
2424
let result = backend.initialize(params).await.unwrap();
2525

2626
let caps = result.capabilities;
27-
assert!(
28-
caps.hover_provider.is_some(),
29-
"Hover provider should be enabled"
30-
);
3127
assert!(
3228
caps.completion_provider.is_some(),
3329
"Completion provider should be enabled"
@@ -39,7 +35,7 @@ async fn test_did_open_stores_file() {
3935
let backend = create_test_backend();
4036

4137
let uri = Url::parse("file:///test.php").unwrap();
42-
let text = "<?php\necho 'hello';\n".to_string();
38+
let text = "<?php\nclass Stored { function m() {} }\n".to_string();
4339

4440
let params = DidOpenTextDocumentParams {
4541
text_document: TextDocumentItem {
@@ -52,99 +48,13 @@ async fn test_did_open_stores_file() {
5248

5349
backend.did_open(params).await;
5450

55-
// Verify by requesting a hover (which accesses stored content)
56-
let hover_params = HoverParams {
57-
text_document_position_params: TextDocumentPositionParams {
58-
text_document: TextDocumentIdentifier { uri },
59-
position: Position {
60-
line: 0,
61-
character: 0,
62-
},
63-
},
64-
work_done_progress_params: WorkDoneProgressParams::default(),
65-
};
66-
67-
let result = backend.hover(hover_params).await;
68-
assert!(result.is_ok());
69-
}
70-
71-
#[tokio::test]
72-
async fn test_hover_on_phpantom() {
73-
let backend = create_test_backend();
74-
75-
let uri = Url::parse("file:///test.php").unwrap();
76-
let text = "<?php\nPHPantom\n".to_string();
77-
78-
let open_params = DidOpenTextDocumentParams {
79-
text_document: TextDocumentItem {
80-
uri: uri.clone(),
81-
language_id: "php".to_string(),
82-
version: 1,
83-
text,
84-
},
85-
};
86-
backend.did_open(open_params).await;
87-
88-
let hover_params = HoverParams {
89-
text_document_position_params: TextDocumentPositionParams {
90-
text_document: TextDocumentIdentifier { uri },
91-
position: Position {
92-
line: 1,
93-
character: 3,
94-
},
95-
},
96-
work_done_progress_params: WorkDoneProgressParams::default(),
97-
};
98-
99-
let result = backend.hover(hover_params).await.unwrap();
100-
assert!(
101-
result.is_some(),
102-
"Hover should return a result for PHPantom"
103-
);
104-
105-
if let Some(hover) = result {
106-
match hover.contents {
107-
HoverContents::Scalar(MarkedString::String(s)) => {
108-
assert_eq!(s, "Welcome to PHPantomLSP!");
109-
}
110-
_ => panic!("Unexpected hover content type"),
111-
}
112-
}
113-
}
114-
115-
#[tokio::test]
116-
async fn test_hover_on_other_word_returns_none() {
117-
let backend = create_test_backend();
118-
119-
let uri = Url::parse("file:///test.php").unwrap();
120-
let text = "<?php\nhelloworld\n".to_string();
121-
122-
let open_params = DidOpenTextDocumentParams {
123-
text_document: TextDocumentItem {
124-
uri: uri.clone(),
125-
language_id: "php".to_string(),
126-
version: 1,
127-
text,
128-
},
129-
};
130-
backend.did_open(open_params).await;
131-
132-
let hover_params = HoverParams {
133-
text_document_position_params: TextDocumentPositionParams {
134-
text_document: TextDocumentIdentifier { uri },
135-
position: Position {
136-
line: 1,
137-
character: 3,
138-
},
139-
},
140-
work_done_progress_params: WorkDoneProgressParams::default(),
141-
};
142-
143-
let result = backend.hover(hover_params).await.unwrap();
51+
// Verify the file was stored by checking the AST map has an entry
52+
let classes = backend.get_classes_for_uri(&uri.to_string());
14453
assert!(
145-
result.is_none(),
146-
"Hover should return None for non-PHPantom words"
54+
classes.is_some(),
55+
"AST map should have an entry after did_open"
14756
);
57+
assert_eq!(classes.unwrap().len(), 1);
14858
}
14959

15060
#[tokio::test]
@@ -201,7 +111,7 @@ async fn test_did_change_updates_content() {
201111
let backend = create_test_backend();
202112

203113
let uri = Url::parse("file:///test.php").unwrap();
204-
let initial_text = "<?php\nPHPantom\n".to_string();
114+
let initial_text = "<?php\nclass A { function first() {} }\n".to_string();
205115

206116
let open_params = DidOpenTextDocumentParams {
207117
text_document: TextDocumentItem {
@@ -213,7 +123,10 @@ async fn test_did_change_updates_content() {
213123
};
214124
backend.did_open(open_params).await;
215125

216-
// Change the content to something else
126+
let classes = backend.get_classes_for_uri(&uri.to_string()).unwrap();
127+
assert_eq!(classes[0].methods.len(), 1);
128+
129+
// Change the content to add a second method
217130
let change_params = DidChangeTextDocumentParams {
218131
text_document: VersionedTextDocumentIdentifier {
219132
uri: uri.clone(),
@@ -222,27 +135,17 @@ async fn test_did_change_updates_content() {
222135
content_changes: vec![TextDocumentContentChangeEvent {
223136
range: None,
224137
range_length: None,
225-
text: "<?php\nhelloworld\n".to_string(),
138+
text: "<?php\nclass A { function first() {} function second() {} }\n".to_string(),
226139
}],
227140
};
228141
backend.did_change(change_params).await;
229142

230-
// Hover should now return None since "PHPantom" is gone
231-
let hover_params = HoverParams {
232-
text_document_position_params: TextDocumentPositionParams {
233-
text_document: TextDocumentIdentifier { uri },
234-
position: Position {
235-
line: 1,
236-
character: 3,
237-
},
238-
},
239-
work_done_progress_params: WorkDoneProgressParams::default(),
240-
};
241-
242-
let result = backend.hover(hover_params).await.unwrap();
243-
assert!(
244-
result.is_none(),
245-
"After change, hover should not find PHPantom"
143+
// Verify content was updated by checking the re-parsed AST
144+
let classes = backend.get_classes_for_uri(&uri.to_string()).unwrap();
145+
assert_eq!(
146+
classes[0].methods.len(),
147+
2,
148+
"After change, class should have 2 methods"
246149
);
247150
}
248151

@@ -251,7 +154,7 @@ async fn test_did_close_removes_file() {
251154
let backend = create_test_backend();
252155

253156
let uri = Url::parse("file:///test.php").unwrap();
254-
let text = "<?php\nPHPantom\n".to_string();
157+
let text = "<?php\nclass Z { function z() {} }\n".to_string();
255158

256159
let open_params = DidOpenTextDocumentParams {
257160
text_document: TextDocumentItem {
@@ -263,26 +166,19 @@ async fn test_did_close_removes_file() {
263166
};
264167
backend.did_open(open_params).await;
265168

169+
assert!(backend.get_classes_for_uri(&uri.to_string()).is_some());
170+
266171
// Close the file
267172
let close_params = DidCloseTextDocumentParams {
268173
text_document: TextDocumentIdentifier { uri: uri.clone() },
269174
};
270175
backend.did_close(close_params).await;
271176

272-
// Hover should return None since the file is closed
273-
let hover_params = HoverParams {
274-
text_document_position_params: TextDocumentPositionParams {
275-
text_document: TextDocumentIdentifier { uri },
276-
position: Position {
277-
line: 1,
278-
character: 3,
279-
},
280-
},
281-
work_done_progress_params: WorkDoneProgressParams::default(),
282-
};
283-
284-
let result = backend.hover(hover_params).await.unwrap();
285-
assert!(result.is_none(), "After close, hover should return None");
177+
// AST map entry should be removed after close
178+
assert!(
179+
backend.get_classes_for_uri(&uri.to_string()).is_none(),
180+
"After close, AST map should not have an entry"
181+
);
286182
}
287183

288184
// ─── AST Parsing Tests ─────────────────────────────────────────────────────

0 commit comments

Comments
 (0)