Migate PHP Extension to zed-extensions/php (#24583)

Peter Tripp created

PHP Extension has been extracted to it's own repository available here:
- https://github.com/zed-extensions/php

Change summary

Cargo.lock                                          |   7 
Cargo.toml                                          |   1 
extensions/php/Cargo.toml                           |  16 -
extensions/php/LICENSE-APACHE                       |   1 
extensions/php/extension.toml                       |  25 -
extensions/php/languages/php/brackets.scm           |   4 
extensions/php/languages/php/config.toml            |  18 -
extensions/php/languages/php/embedding.scm          |  36 --
extensions/php/languages/php/highlights.scm         | 137 ---------
extensions/php/languages/php/indents.scm            |   1 
extensions/php/languages/php/injections.scm         |  11 
extensions/php/languages/php/outline.scm            |  46 ---
extensions/php/languages/php/runnables.scm          | 105 -------
extensions/php/languages/php/tags.scm               |  40 --
extensions/php/languages/php/tasks.json             |  19 -
extensions/php/languages/php/textobjects.scm        |  45 ---
extensions/php/languages/phpdoc/config.toml         |   9 
extensions/php/languages/phpdoc/highlights.scm      |  13 
extensions/php/src/language_servers.rs              |   5 
extensions/php/src/language_servers/intelephense.rs | 209 ---------------
extensions/php/src/language_servers/phpactor.rs     |  85 ------
extensions/php/src/php.rs                           |  72 -----
22 files changed, 905 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -16823,13 +16823,6 @@ dependencies = [
  "zed_extension_api 0.1.0",
 ]
 
-[[package]]
-name = "zed_php"
-version = "0.2.4"
-dependencies = [
- "zed_extension_api 0.1.0",
-]
-
 [[package]]
 name = "zed_proto"
 version = "0.2.1"

Cargo.toml 🔗

@@ -171,7 +171,6 @@ members = [
     "extensions/haskell",
     "extensions/html",
     "extensions/lua",
-    "extensions/php",
     "extensions/perplexity",
     "extensions/proto",
     "extensions/purescript",

extensions/php/Cargo.toml 🔗

@@ -1,16 +0,0 @@
-[package]
-name = "zed_php"
-version = "0.2.4"
-edition.workspace = true
-publish.workspace = true
-license = "Apache-2.0"
-
-[lints]
-workspace = true
-
-[lib]
-path = "src/php.rs"
-crate-type = ["cdylib"]
-
-[dependencies]
-zed_extension_api = "0.1.0"

extensions/php/extension.toml 🔗

@@ -1,25 +0,0 @@
-id = "php"
-name = "PHP"
-description = "PHP support."
-version = "0.2.4"
-schema_version = 1
-authors = ["Piotr Osiewicz <piotr@zed.dev>"]
-repository = "https://github.com/zed-industries/zed"
-
-[language_servers.intelephense]
-name = "Intelephense"
-language = "PHP"
-language_ids = { PHP = "php"}
-
-[language_servers.phpactor]
-name = "Phpactor"
-language = "PHP"
-
-[grammars.php]
-repository = "https://github.com/tree-sitter/tree-sitter-php"
-commit = "8ab93274065cbaf529ea15c24360cfa3348ec9e4"
-path = "php"
-
-[grammars.phpdoc]
-repository = "https://github.com/claytonrcarter/tree-sitter-phpdoc"
-commit = "1d0e255b37477d0ca46f1c9e9268c8fa76c0b3fc"

extensions/php/languages/php/config.toml 🔗

@@ -1,18 +0,0 @@
-name = "PHP"
-grammar = "php"
-path_suffixes = ["php"]
-first_line_pattern = '^#!.*php'
-line_comments = ["// ", "# "]
-autoclose_before = ";:.,=}])>"
-brackets = [
-    { start = "{", end = "}", close = true, newline = true },
-    { start = "[", end = "]", close = true, newline = true },
-    { start = "(", end = ")", close = true, newline = true },
-    { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] },
-    { start = "'", end = "'", close = true, newline = false, not_in = ["string"] },
-]
-collapsed_placeholder = "/* ... */"
-word_characters = ["$"]
-scope_opt_in_language_servers = ["tailwindcss-language-server"]
-prettier_parser_name = "php"
-prettier_plugins = ["@prettier/plugin-php"]

extensions/php/languages/php/embedding.scm 🔗

@@ -1,36 +0,0 @@
-(
-    (comment)* @context
-    .
-    [
-        (function_definition
-            "function" @name
-            name: (_) @name
-            body: (_
-                "{" @keep
-                "}" @keep) @collapse
-            )
-
-        (trait_declaration
-            "trait" @name
-            name: (_) @name)
-
-        (method_declaration
-            "function" @name
-            name: (_) @name
-            body: (_
-                "{" @keep
-                "}" @keep) @collapse
-            )
-
-        (interface_declaration
-            "interface" @name
-            name: (_) @name
-            )
-
-        (enum_declaration
-            "enum" @name
-            name: (_) @name
-            )
-
-        ] @item
-    )

extensions/php/languages/php/highlights.scm 🔗

@@ -1,137 +0,0 @@
-(php_tag) @tag
-"?>" @tag
-
-; Types
-
-(primitive_type) @type.builtin
-(cast_type) @type.builtin
-(named_type (name) @type) @type
-(named_type (qualified_name) @type) @type
-
-; Functions
-
-(array_creation_expression "array" @function.builtin)
-(list_literal "list" @function.builtin)
-
-(method_declaration
-  name: (name) @function.method)
-
-(function_call_expression
-  function: [(qualified_name (name)) (name)] @function)
-
-(scoped_call_expression
-  name: (name) @function)
-
-(member_call_expression
-  name: (name) @function.method)
-
-(function_definition
-  name: (name) @function)
-
-; Member
-
-(property_element
-  (variable_name) @property)
-
-(member_access_expression
-  name: (variable_name (name)) @property)
-(member_access_expression
-  name: (name) @property)
-
-; Variables
-
-(relative_scope) @variable.builtin
-
-((name) @constant
- (#match? @constant "^_?[A-Z][A-Z\\d_]+$"))
-((name) @constant.builtin
- (#match? @constant.builtin "^__[A-Z][A-Z\d_]+__$"))
-
-((name) @constructor
- (#match? @constructor "^[A-Z]"))
-
-((name) @variable.builtin
- (#eq? @variable.builtin "this"))
-
-(variable_name) @variable
-
-; Basic tokens
-[
-  (string)
-  (string_value)
-  (encapsed_string)
-  (heredoc)
-  (heredoc_body)
-  (nowdoc_body)
-] @string
-(boolean) @constant.builtin
-(null) @constant.builtin
-(integer) @number
-(float) @number
-(comment) @comment
-
-"$" @operator
-
-; Keywords
-
-"abstract" @keyword
-"and" @keyword
-"as" @keyword
-"break" @keyword
-"callable" @keyword
-"case" @keyword
-"catch" @keyword
-"class" @keyword
-"clone" @keyword
-"const" @keyword
-"continue" @keyword
-"declare" @keyword
-"default" @keyword
-"do" @keyword
-"echo" @keyword
-"else" @keyword
-"elseif" @keyword
-"enum" @keyword
-"enddeclare" @keyword
-"endfor" @keyword
-"endforeach" @keyword
-"endif" @keyword
-"endswitch" @keyword
-"endwhile" @keyword
-"extends" @keyword
-"final" @keyword
-"readonly" @keyword
-"finally" @keyword
-"for" @keyword
-"foreach" @keyword
-"fn" @keyword
-"function" @keyword
-"global" @keyword
-"goto" @keyword
-"if" @keyword
-"implements" @keyword
-"include_once" @keyword
-"include" @keyword
-"instanceof" @keyword
-"insteadof" @keyword
-"interface" @keyword
-"match" @keyword
-"namespace" @keyword
-"new" @keyword
-"or" @keyword
-"print" @keyword
-"private" @keyword
-"protected" @keyword
-"public" @keyword
-"readonly" @keyword
-"require_once" @keyword
-"require" @keyword
-"return" @keyword
-"static" @keyword
-"switch" @keyword
-"throw" @keyword
-"trait" @keyword
-"try" @keyword
-"use" @keyword
-"while" @keyword
-"xor" @keyword

extensions/php/languages/php/injections.scm 🔗

@@ -1,11 +0,0 @@
-((text) @injection.content
- (#set! injection.language "html")
- (#set! injection.combined))
-
-((comment) @injection.content
-  (#match? @injection.content "^/\\*\\*[^*]")
-  (#set! injection.language "phpdoc"))
-
-((heredoc_body) (heredoc_end) @injection.language) @injection.content
-
-((nowdoc_body) (heredoc_end) @injection.language) @injection.content

extensions/php/languages/php/outline.scm 🔗

@@ -1,46 +0,0 @@
-(class_declaration
-    "class" @context
-    name: (name) @name
-    ) @item
-
-(function_definition
-    "function" @context
-    name: (_) @name
-    ) @item
-
-(method_declaration
-    "function" @context
-    name: (_) @name
-    ) @item
-
-(interface_declaration
-    "interface" @context
-    name: (_) @name
-    ) @item
-
-(enum_declaration
-    "enum" @context
-    name: (_) @name
-    ) @item
-
-(trait_declaration
-    "trait" @context
-    name: (_) @name
-    ) @item
-
-; Add support for Pest runnable
-(function_call_expression
-    function: (_) @context
-    (#any-of? @context "it" "test" "describe")
-    arguments: (arguments
-        .
-        (argument
-            [
-              (encapsed_string (string_value) @name)
-              (string (string_value) @name)
-            ]
-        )
-    )
-) @item
-
-(comment) @annotation

extensions/php/languages/php/runnables.scm 🔗

@@ -1,105 +0,0 @@
-; Class that follow the naming convention of PHPUnit test classes
-; and that doesn't have the abstract modifier
-; and have a method that follow the naming convention of PHPUnit test methods
-; and the method is public
-(
-    (class_declaration
-        modifier: (_)? @_modifier
-        (#not-eq? @_modifier "abstract")
-        name: (_) @_name
-        (#match? @_name ".*Test$")
-        body: (declaration_list
-            (method_declaration
-                (visibility_modifier)? @_visibility
-                (#eq? @_visibility "public")
-                name: (_) @run
-                (#match? @run "^test.*")
-            )
-        )
-    ) @_phpunit-test
-    (#set! tag phpunit-test)
-)
-
-; Class that follow the naming convention of PHPUnit test classes
-; and that doesn't have the abstract modifier
-; and have a method that has the @test annotation
-; and the method is public
-(
-    (class_declaration
-        modifier: (_)? @_modifier
-        (#not-eq? @_modifier "abstract")
-        name: (_) @_name
-        (#match? @_name ".*Test$")
-        body: (declaration_list
-            ((comment) @_comment
-                (#match? @_comment ".*@test\\b.*")
-            .
-            (method_declaration
-                (visibility_modifier)? @_visibility
-                (#eq? @_visibility "public")
-                name: (_) @run
-                (#not-match? @run "^test.*")
-            ))
-        )
-    ) @_phpunit-test
-    (#set! tag phpunit-test)
-)
-
-; Class that follow the naming convention of PHPUnit test classes
-; and that doesn't have the abstract modifier
-; and have a method that has the #[Test] attribute
-; and the method is public
-(
-    (class_declaration
-        modifier: (_)? @_modifier
-        (#not-eq? @_modifier "abstract")
-        name: (_) @_name
-        (#match? @_name ".*Test$")
-        body: (declaration_list
-            (method_declaration
-                (attribute_list
-                    (attribute_group
-                        (attribute (name) @_attribute)
-                    )
-                )
-                (#eq? @_attribute "Test")
-                (visibility_modifier)? @_visibility
-                (#eq? @_visibility "public")
-                name: (_) @run
-                (#not-match? @run "^test.*")
-            )
-        )
-    ) @_phpunit-test
-    (#set! tag phpunit-test)
-)
-
-; Class that follow the naming convention of PHPUnit test classes
-; and that doesn't have the abstract modifier
-(
-    (class_declaration
-        modifier: (_)? @_modifier
-        (#not-eq? @_modifier "abstract")
-        name: (_) @run
-        (#match? @run ".*Test$")
-    ) @_phpunit-test
-    (#set! tag phpunit-test)
-)
-
-; Add support for Pest runnable
-; Function expression that has `it`, `test` or `describe` as the function name
-(
-    (function_call_expression
-        function: (_) @_name
-        (#any-of? @_name "it" "test" "describe")
-        arguments: (arguments
-            .
-            (argument
-                [
-                  (encapsed_string (string_value) @run)
-                  (string (string_value) @run)
-                ]
-            )
-        )
-    ) @_pest-test
-    (#set! tag pest-test)
-)

extensions/php/languages/php/tags.scm 🔗

@@ -1,40 +0,0 @@
-(namespace_definition
-  name: (namespace_name) @name) @module
-
-(interface_declaration
-  name: (name) @name) @definition.interface
-
-(trait_declaration
-  name: (name) @name) @definition.interface
-
-(class_declaration
-  name: (name) @name) @definition.class
-
-(class_interface_clause [(name) (qualified_name)] @name) @impl
-
-(property_declaration
-  (property_element (variable_name (name) @name))) @definition.field
-
-(function_definition
-  name: (name) @name) @definition.function
-
-(method_declaration
-  name: (name) @name) @definition.function
-
-(object_creation_expression
-  [
-    (qualified_name (name) @name)
-    (variable_name (name) @name)
-  ]) @reference.class
-
-(function_call_expression
-  function: [
-    (qualified_name (name) @name)
-    (variable_name (name)) @name
-  ]) @reference.call
-
-(scoped_call_expression
-  name: (name) @name) @reference.call
-
-(member_call_expression
-  name: (name) @name) @reference.call

extensions/php/languages/php/tasks.json 🔗

@@ -1,19 +0,0 @@
-[
-  {
-    "label": "phpunit test $ZED_SYMBOL",
-    "command": "./vendor/bin/phpunit",
-    "args": ["--filter $ZED_SYMBOL $ZED_FILE"],
-    "tags": ["phpunit-test"]
-  },
-  {
-    "label": "pest test $ZED_SYMBOL",
-    "command": "./vendor/bin/pest",
-    "args": ["--filter \"$ZED_SYMBOL\" $ZED_FILE"],
-    "tags": ["pest-test"]
-  },
-  {
-    "label": "execute selection $ZED_SELECTED_TEXT",
-    "command": "php",
-    "args": ["-r", "$ZED_SELECTED_TEXT"]
-  }
-]

extensions/php/languages/php/textobjects.scm 🔗

@@ -1,45 +0,0 @@
-(function_definition
-    body: (_
-        "{"
-        (_)* @function.inside
-        "}" )) @function.around
-
-(method_declaration
-    body: (_
-        "{"
-        (_)* @function.inside
-        "}" )) @function.around
-
-(method_declaration) @function.around
-
-(class_declaration
-    body: (_
-        "{"
-        (_)* @class.inside
-        "}")) @class.around
-
-(interface_declaration
-    body: (_
-        "{"
-        (_)* @class.inside
-        "}")) @class.around
-
-(trait_declaration
-    body: (_
-        "{"
-        (_)* @class.inside
-        "}")) @class.around
-
-(enum_declaration
-    body: (_
-        "{"
-        (_)* @class.inside
-        "}")) @class.around
-
-(namespace_definition
-    body: (_
-        "{"
-        (_)* @class.inside
-        "}")) @class.around
-
-(comment)+ @comment.around

extensions/php/languages/phpdoc/config.toml 🔗

@@ -1,9 +0,0 @@
-name = "PHPDoc"
-grammar = "phpdoc"
-autoclose_before = "]})>"
-brackets = [
-  { start = "{", end = "}", close = true, newline = false },
-  { start = "[", end = "]", close = true, newline = false },
-  { start = "(", end = ")", close = true, newline = false },
-  { start = "<", end = ">", close = true, newline = false },
-]

extensions/php/languages/phpdoc/highlights.scm 🔗

@@ -1,13 +0,0 @@
-(tag_name) @keyword
-
-(tag (variable_name) @variable)
-(variable_name "$" @operator)
-
-(tag
-  (tag_name) @keyword
-  (#eq? @keyword "@method")
-  (name) @function.method)
-
-(primitive_type) @type.builtin
-(named_type (name) @type) @type
-(named_type (qualified_name) @type) @type

extensions/php/src/language_servers/intelephense.rs 🔗

@@ -1,209 +0,0 @@
-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};
-
-const SERVER_PATH: &str = "node_modules/intelephense/lib/intelephense.js";
-const PACKAGE_NAME: &str = "intelephense";
-
-pub struct Intelephense {
-    did_find_server: bool,
-}
-
-impl Intelephense {
-    pub const LANGUAGE_SERVER_ID: &'static str = "intelephense";
-
-    pub fn new() -> Self {
-        Self {
-            did_find_server: false,
-        }
-    }
-
-    pub fn language_server_command(
-        &mut self,
-        language_server_id: &LanguageServerId,
-        worktree: &zed::Worktree,
-    ) -> Result<zed::Command> {
-        if let Some(path) = worktree.which("intelephense") {
-            return Ok(zed::Command {
-                command: path,
-                args: vec!["--stdio".to_string()],
-                env: Default::default(),
-            });
-        }
-
-        let server_path = self.server_script_path(language_server_id)?;
-        Ok(zed::Command {
-            command: zed::node_binary_path()?,
-            args: vec![
-                env::current_dir()
-                    .unwrap()
-                    .join(&server_path)
-                    .to_string_lossy()
-                    .to_string(),
-                "--stdio".to_string(),
-            ],
-            env: Default::default(),
-        })
-    }
-
-    fn server_exists(&self) -> bool {
-        fs::metadata(SERVER_PATH).map_or(false, |stat| stat.is_file())
-    }
-
-    fn server_script_path(&mut self, language_server_id: &LanguageServerId) -> Result<String> {
-        let server_exists = self.server_exists();
-        if self.did_find_server && server_exists {
-            return Ok(SERVER_PATH.to_string());
-        }
-
-        zed::set_language_server_installation_status(
-            language_server_id,
-            &zed::LanguageServerInstallationStatus::CheckingForUpdate,
-        );
-        let version = zed::npm_package_latest_version(PACKAGE_NAME)?;
-
-        if !server_exists
-            || zed::npm_package_installed_version(PACKAGE_NAME)?.as_ref() != Some(&version)
-        {
-            zed::set_language_server_installation_status(
-                language_server_id,
-                &zed::LanguageServerInstallationStatus::Downloading,
-            );
-            let result = zed::npm_install_package(PACKAGE_NAME, &version);
-            match result {
-                Ok(()) => {
-                    if !self.server_exists() {
-                        Err(format!(
-                            "installed package '{PACKAGE_NAME}' did not contain expected path '{SERVER_PATH}'",
-                        ))?;
-                    }
-                }
-                Err(error) => {
-                    if !self.server_exists() {
-                        Err(error)?;
-                    }
-                }
-            }
-        }
-
-        self.did_find_server = true;
-        Ok(SERVER_PATH.to_string())
-    }
-
-    pub fn language_server_workspace_configuration(
-        &mut self,
-        worktree: &zed::Worktree,
-    ) -> Result<Option<serde_json::Value>> {
-        let settings = LspSettings::for_worktree("intelephense", worktree)
-            .ok()
-            .and_then(|lsp_settings| lsp_settings.settings.clone())
-            .unwrap_or_default();
-
-        Ok(Some(serde_json::json!({
-            "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,
-        }
-    }
-}

extensions/php/src/language_servers/phpactor.rs 🔗

@@ -1,85 +0,0 @@
-use std::fs;
-
-use zed_extension_api::{self as zed, LanguageServerId, Result};
-
-pub struct Phpactor {
-    cached_binary_path: Option<String>,
-}
-
-impl Phpactor {
-    pub const LANGUAGE_SERVER_ID: &'static str = "phpactor";
-
-    pub fn new() -> Self {
-        Self {
-            cached_binary_path: None,
-        }
-    }
-
-    pub fn language_server_binary_path(
-        &mut self,
-        language_server_id: &LanguageServerId,
-        worktree: &zed::Worktree,
-    ) -> Result<String> {
-        if let Some(path) = worktree.which("phpactor") {
-            return Ok(path);
-        }
-
-        if let Some(path) = &self.cached_binary_path {
-            if fs::metadata(path).map_or(false, |stat| stat.is_file()) {
-                return Ok(path.clone());
-            }
-        }
-
-        zed::set_language_server_installation_status(
-            language_server_id,
-            &zed::LanguageServerInstallationStatus::CheckingForUpdate,
-        );
-        let release = zed::latest_github_release(
-            "phpactor/phpactor",
-            zed::GithubReleaseOptions {
-                require_assets: true,
-                pre_release: false,
-            },
-        )?;
-
-        let asset_name = "phpactor.phar";
-        let asset = release
-            .assets
-            .iter()
-            .find(|asset| asset.name == asset_name)
-            .ok_or_else(|| format!("no asset found matching {:?}", asset_name))?;
-
-        let version_dir = format!("phpactor-{}", release.version);
-        fs::create_dir_all(&version_dir).map_err(|e| format!("failed to create directory: {e}"))?;
-
-        let binary_path = format!("{version_dir}/phpactor.phar");
-
-        if !fs::metadata(&binary_path).map_or(false, |stat| stat.is_file()) {
-            zed::set_language_server_installation_status(
-                language_server_id,
-                &zed::LanguageServerInstallationStatus::Downloading,
-            );
-
-            zed::download_file(
-                &asset.download_url,
-                &binary_path,
-                zed::DownloadedFileType::Uncompressed,
-            )
-            .map_err(|e| format!("failed to download file: {e}"))?;
-
-            zed::make_file_executable(&binary_path)?;
-
-            let entries =
-                fs::read_dir(".").map_err(|e| format!("failed to list working directory {e}"))?;
-            for entry in entries {
-                let entry = entry.map_err(|e| format!("failed to load directory entry {e}"))?;
-                if entry.file_name().to_str() != Some(&version_dir) {
-                    fs::remove_dir_all(entry.path()).ok();
-                }
-            }
-        }
-
-        self.cached_binary_path = Some(binary_path.clone());
-        Ok(binary_path)
-    }
-}

extensions/php/src/php.rs 🔗

@@ -1,72 +0,0 @@
-mod language_servers;
-
-use zed::CodeLabel;
-use zed_extension_api::{self as zed, serde_json, LanguageServerId, Result};
-
-use crate::language_servers::{Intelephense, Phpactor};
-
-struct PhpExtension {
-    intelephense: Option<Intelephense>,
-    phpactor: Option<Phpactor>,
-}
-
-impl zed::Extension for PhpExtension {
-    fn new() -> Self {
-        Self {
-            intelephense: None,
-            phpactor: None,
-        }
-    }
-
-    fn language_server_command(
-        &mut self,
-        language_server_id: &LanguageServerId,
-        worktree: &zed::Worktree,
-    ) -> Result<zed::Command> {
-        match language_server_id.as_ref() {
-            Intelephense::LANGUAGE_SERVER_ID => {
-                let intelephense = self.intelephense.get_or_insert_with(Intelephense::new);
-                intelephense.language_server_command(language_server_id, worktree)
-            }
-            Phpactor::LANGUAGE_SERVER_ID => {
-                let phpactor = self.phpactor.get_or_insert_with(Phpactor::new);
-
-                Ok(zed::Command {
-                    command: phpactor.language_server_binary_path(language_server_id, worktree)?,
-                    args: vec!["language-server".into()],
-                    env: Default::default(),
-                })
-            }
-            language_server_id => Err(format!("unknown language server: {language_server_id}")),
-        }
-    }
-
-    fn language_server_workspace_configuration(
-        &mut self,
-        language_server_id: &LanguageServerId,
-        worktree: &zed::Worktree,
-    ) -> Result<Option<serde_json::Value>> {
-        if language_server_id.as_ref() == Intelephense::LANGUAGE_SERVER_ID {
-            if let Some(intelephense) = self.intelephense.as_mut() {
-                return intelephense.language_server_workspace_configuration(worktree);
-            }
-        }
-
-        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);