mirror of
https://github.com/zed-industries/zed.git
synced 2024-10-23 06:56:33 +00:00
php: Add syntax highlighting for Intelephense completions (#18774)
Release Notes: - N/A This PR introduces syntax highlighting for intelephense autocomple. The styling was selected to roughly match PHPStorm's default scheme. Please note that I'm not very familiar with writing Rust, but I'm happy to adapt to any requested changes! ## Examples ### Object attributes, methods and constants ![Screenshot 2024-10-06 at 13 38 03](https://github.com/user-attachments/assets/a91634ff-0f2e-41f0-b548-ecb09c40947c) ![Screenshot 2024-10-06 at 13 38 11](https://github.com/user-attachments/assets/b6f179f4-898b-4d82-9d36-a3e82328325c) ### Typed enum members ![Screenshot 2024-10-06 at 13 38 53](https://github.com/user-attachments/assets/7133b981-4f68-4210-b233-403cdf3ec9bb) ![Screenshot 2024-10-06 at 13 38 41](https://github.com/user-attachments/assets/2e806f3d-3538-45f2-b075-b8be5902b786) ### Variables Includes altered highlighting for [reserved variable names](https://www.php.net/manual/en/reserved.variables.php). ![Screenshot 2024-10-06 at 13 39 30](https://github.com/user-attachments/assets/be426eb8-5879-432d-b302-391c2c68a7cb) --------- Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
8376dd2011
commit
200b2bf70a
2 changed files with 116 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
|||
use std::{env, fs};
|
||||
|
||||
use zed::{CodeLabel, CodeLabelSpan};
|
||||
use zed_extension_api::settings::LspSettings;
|
||||
use zed_extension_api::{self as zed, serde_json, LanguageServerId, Result};
|
||||
|
||||
|
@ -104,4 +105,105 @@ impl Intelephense {
|
|||
"intelephense": settings
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn label_for_completion(&self, completion: zed::lsp::Completion) -> Option<CodeLabel> {
|
||||
let label = &completion.label;
|
||||
|
||||
match completion.kind? {
|
||||
zed::lsp::CompletionKind::Method => {
|
||||
// __construct method doesn't have a detail
|
||||
if let Some(ref detail) = completion.detail {
|
||||
if detail.is_empty() {
|
||||
return Some(CodeLabel {
|
||||
spans: vec![
|
||||
CodeLabelSpan::literal(label, Some("function.method".to_string())),
|
||||
CodeLabelSpan::literal("()", None),
|
||||
],
|
||||
filter_range: (0..label.len()).into(),
|
||||
code: completion.label,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut parts = completion.detail.as_ref()?.split(":");
|
||||
// E.g., `foo(string $var)`
|
||||
let name_and_params = parts.next()?;
|
||||
let return_type = parts.next()?.trim();
|
||||
|
||||
let (_, params) = name_and_params.split_once("(")?;
|
||||
let params = params.trim_end_matches(")");
|
||||
|
||||
Some(CodeLabel {
|
||||
spans: vec![
|
||||
CodeLabelSpan::literal(label, Some("function.method".to_string())),
|
||||
CodeLabelSpan::literal("(", None),
|
||||
CodeLabelSpan::literal(params, Some("comment".to_string())),
|
||||
CodeLabelSpan::literal("): ", None),
|
||||
CodeLabelSpan::literal(return_type, Some("type".to_string())),
|
||||
],
|
||||
filter_range: (0..label.len()).into(),
|
||||
code: completion.label,
|
||||
})
|
||||
}
|
||||
zed::lsp::CompletionKind::Constant | zed::lsp::CompletionKind::EnumMember => {
|
||||
if let Some(ref detail) = completion.detail {
|
||||
if !detail.is_empty() {
|
||||
return Some(CodeLabel {
|
||||
spans: vec![
|
||||
CodeLabelSpan::literal(label, Some("constant".to_string())),
|
||||
CodeLabelSpan::literal(" ", None),
|
||||
CodeLabelSpan::literal(detail, Some("comment".to_string())),
|
||||
],
|
||||
filter_range: (0..label.len()).into(),
|
||||
code: completion.label,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Some(CodeLabel {
|
||||
spans: vec![CodeLabelSpan::literal(label, Some("constant".to_string()))],
|
||||
filter_range: (0..label.len()).into(),
|
||||
code: completion.label,
|
||||
})
|
||||
}
|
||||
zed::lsp::CompletionKind::Property => {
|
||||
let return_type = completion.detail?;
|
||||
Some(CodeLabel {
|
||||
spans: vec![
|
||||
CodeLabelSpan::literal(label, Some("attribute".to_string())),
|
||||
CodeLabelSpan::literal(": ", None),
|
||||
CodeLabelSpan::literal(return_type, Some("type".to_string())),
|
||||
],
|
||||
filter_range: (0..label.len()).into(),
|
||||
code: completion.label,
|
||||
})
|
||||
}
|
||||
zed::lsp::CompletionKind::Variable => {
|
||||
// See https://www.php.net/manual/en/reserved.variables.php
|
||||
const SYSTEM_VAR_NAMES: &[&str] =
|
||||
&["argc", "argv", "php_errormsg", "http_response_header"];
|
||||
|
||||
let var_name = completion.label.trim_start_matches("$");
|
||||
let is_uppercase = var_name
|
||||
.chars()
|
||||
.filter(|c| c.is_alphabetic())
|
||||
.all(|c| c.is_uppercase());
|
||||
let is_system_constant = var_name.starts_with("_");
|
||||
let is_reserved = SYSTEM_VAR_NAMES.contains(&var_name);
|
||||
|
||||
let highlight = if is_uppercase || is_system_constant || is_reserved {
|
||||
Some("comment".to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(CodeLabel {
|
||||
spans: vec![CodeLabelSpan::literal(label, highlight)],
|
||||
filter_range: (0..label.len()).into(),
|
||||
code: completion.label,
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod language_servers;
|
||||
|
||||
use zed::CodeLabel;
|
||||
use zed_extension_api::{self as zed, serde_json, LanguageServerId, Result};
|
||||
|
||||
use crate::language_servers::{Intelephense, Phpactor};
|
||||
|
@ -53,6 +54,19 @@ impl zed::Extension for PhpExtension {
|
|||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn label_for_completion(
|
||||
&self,
|
||||
language_server_id: &zed::LanguageServerId,
|
||||
completion: zed::lsp::Completion,
|
||||
) -> Option<CodeLabel> {
|
||||
match language_server_id.as_ref() {
|
||||
Intelephense::LANGUAGE_SERVER_ID => {
|
||||
self.intelephense.as_ref()?.label_for_completion(completion)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zed::register_extension!(PhpExtension);
|
||||
|
|
Loading…
Reference in a new issue