csharp: Extract to zed-extensions/csharp repository (#26166)

This PR extracts the C# extension to the
[zed-extensions/csharp](https://github.com/zed-extensions/csharp)
repository.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-03-05 17:23:49 -05:00 committed by GitHub
parent cee98f872a
commit 431727fdd7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1 additions and 501 deletions

View file

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

View file

@ -1 +0,0 @@
../../LICENSE-APACHE

View file

@ -1,15 +0,0 @@
id = "csharp"
name = "C#"
description = "C# support."
version = "0.1.1"
schema_version = 1
authors = ["fminkowski <fminkowski@gmail.com>"]
repository = "https://github.com/zed-industries/zed"
[language_servers.omnisharp]
name = "OmniSharp"
language = "CSharp"
[grammars.c_sharp]
repository = "https://github.com/tree-sitter/tree-sitter-c-sharp"
commit = "dd5e59721a5f8dae34604060833902b882023aaf"

View file

@ -1,5 +0,0 @@
("(" @open ")" @close)
("[" @open "]" @close)
("{" @open "}" @close)
("<" @open ">" @close)
("\"" @open "\"" @close)

View file

@ -1,14 +0,0 @@
name = "CSharp"
code_fence_block_name = "csharp"
grammar = "c_sharp"
path_suffixes = ["cs"]
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", "comment"] },
{ start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] },
]

View file

@ -1,254 +0,0 @@
;; Methods
(method_declaration name: (identifier) @function)
(local_function_statement name: (identifier) @function)
;; Types
(interface_declaration name: (identifier) @type)
(class_declaration name: (identifier) @type)
(enum_declaration name: (identifier) @type)
(struct_declaration (identifier) @type)
(record_declaration (identifier) @type)
(record_struct_declaration (identifier) @type)
(namespace_declaration name: (identifier) @type)
(constructor_declaration name: (identifier) @constructor)
(destructor_declaration name: (identifier) @constructor)
[
(implicit_type)
(predefined_type)
] @type.builtin
(_ type: (identifier) @type)
;; Enum
(enum_member_declaration (identifier) @property)
;; Literals
[
(real_literal)
(integer_literal)
] @number
[
(character_literal)
(string_literal)
(verbatim_string_literal)
(interpolated_string_text)
(interpolated_verbatim_string_text)
"\""
"$\""
"@$\""
"$@\""
] @string
[
(boolean_literal)
(null_literal)
] @constant
;; Comments
(comment) @comment
;; Tokens
[
";"
"."
","
] @punctuation.delimiter
[
"--"
"-"
"-="
"&"
"&="
"&&"
"+"
"++"
"+="
"<"
"<="
"<<"
"<<="
"="
"=="
"!"
"!="
"=>"
">"
">="
">>"
">>="
">>>"
">>>="
"|"
"|="
"||"
"?"
"??"
"??="
"^"
"^="
"~"
"*"
"*="
"/"
"/="
"%"
"%="
":"
] @operator
[
"("
")"
"["
"]"
"{"
"}"
] @punctuation.bracket
;; Keywords
(modifier) @keyword
(this_expression) @keyword
(escape_sequence) @keyword
[
"add"
"alias"
"as"
"base"
"break"
"case"
"catch"
"checked"
"class"
"continue"
"default"
"delegate"
"do"
"else"
"enum"
"event"
"explicit"
"extern"
"finally"
"for"
"foreach"
"global"
"goto"
"if"
"implicit"
"interface"
"is"
"lock"
"namespace"
"notnull"
"operator"
"params"
"return"
"remove"
"sizeof"
"stackalloc"
"static"
"struct"
"switch"
"throw"
"try"
"typeof"
"unchecked"
"using"
"while"
"new"
"await"
"in"
"yield"
"get"
"set"
"when"
"out"
"ref"
"from"
"where"
"select"
"record"
"init"
"with"
"let"
] @keyword
;; Linq
(from_clause (identifier) @variable)
(group_clause (identifier) @variable)
(order_by_clause (identifier) @variable)
(join_clause (identifier) @variable)
(select_clause (identifier) @variable)
(query_continuation (identifier) @variable) @keyword
;; Record
(with_expression
(with_initializer_expression
(simple_assignment_expression
(identifier) @variable)))
;; Exprs
(binary_expression (identifier) @variable (identifier) @variable)
(binary_expression (identifier)* @variable)
(conditional_expression (identifier) @variable)
(prefix_unary_expression (identifier) @variable)
(postfix_unary_expression (identifier)* @variable)
(assignment_expression (identifier) @variable)
(cast_expression (_) (identifier) @variable)
;; Class
(base_list (identifier) @type) ;; applies to record_base too
(property_declaration (generic_name))
(property_declaration
name: (identifier) @variable)
(property_declaration
name: (identifier) @variable)
(property_declaration
name: (identifier) @variable)
;; Lambda
(lambda_expression) @variable
;; Attribute
(attribute) @attribute
;; Parameter
(parameter
name: (identifier) @variable)
(parameter (identifier) @variable)
(parameter_modifier) @keyword
;; Variable declarations
(variable_declarator (identifier) @variable)
(for_each_statement left: (identifier) @variable)
(catch_declaration (_) (identifier) @variable)
;; Return
(return_statement (identifier) @variable)
(yield_statement (identifier) @variable)
;; Type
(generic_name (identifier) @type)
(type_parameter (identifier) @property)
(type_argument_list (identifier) @type)
(as_expression right: (identifier) @type)
(is_expression right: (identifier) @type)
;; Type constraints
(type_parameter_constraints_clause (identifier) @property)
;; Switch
(switch_statement (identifier) @variable)
(switch_expression (identifier) @variable)
;; Lock statement
(lock_statement (identifier) @variable)
;; Method calls
(invocation_expression (member_access_expression name: (identifier) @function))

View file

@ -1,3 +0,0 @@
(_ "{" "}" @end) @indent
(_ "[" "]" @end) @indent
(_ "(" ")" @end) @indent

View file

@ -1,2 +0,0 @@
((comment) @injection.content
(#set! injection.language "comment"))

View file

@ -1,38 +0,0 @@
(class_declaration
"class" @context
name: (identifier) @name
) @item
(constructor_declaration
name: (identifier) @name
) @item
(property_declaration
type: (identifier)? @context
type: (predefined_type)? @context
name: (identifier) @name
) @item
(field_declaration
(variable_declaration) @context
) @item
(method_declaration
name: (identifier) @name
parameters: (parameter_list) @context
) @item
(enum_declaration
"enum" @context
name: (identifier) @name
) @item
(namespace_declaration
"namespace" @context
name: (qualified_name) @name
) @item
(interface_declaration
"interface" @context
name: (identifier) @name
) @item

View file

@ -1,144 +0,0 @@
use std::fs;
use zed_extension_api::{self as zed, settings::LspSettings, LanguageServerId, Result};
struct OmnisharpBinary {
path: String,
args: Option<Vec<String>>,
}
struct CsharpExtension {
cached_binary_path: Option<String>,
}
impl CsharpExtension {
fn language_server_binary(
&mut self,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<OmnisharpBinary> {
let binary_settings = LspSettings::for_worktree("omnisharp", worktree)
.ok()
.and_then(|lsp_settings| lsp_settings.binary);
let binary_args = binary_settings
.as_ref()
.and_then(|binary_settings| binary_settings.arguments.clone());
if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
return Ok(OmnisharpBinary {
path,
args: binary_args,
});
}
if let Some(path) = worktree.which("OmniSharp") {
return Ok(OmnisharpBinary {
path,
args: binary_args,
});
}
if let Some(path) = &self.cached_binary_path {
if fs::metadata(path).map_or(false, |stat| stat.is_file()) {
return Ok(OmnisharpBinary {
path: path.clone(),
args: binary_args,
});
}
}
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
);
let release = zed::latest_github_release(
"OmniSharp/omnisharp-roslyn",
zed::GithubReleaseOptions {
require_assets: true,
pre_release: false,
},
)?;
let (platform, arch) = zed::current_platform();
let asset_name = format!(
"omnisharp-{os}-{arch}-net6.0.{extension}",
os = match platform {
zed::Os::Mac => "osx",
zed::Os::Linux => "linux",
zed::Os::Windows => "win",
},
arch = match arch {
zed::Architecture::Aarch64 => "arm64",
zed::Architecture::X86 => "x86",
zed::Architecture::X8664 => "x64",
},
extension = match platform {
zed::Os::Mac | zed::Os::Linux => "tar.gz",
zed::Os::Windows => "zip",
}
);
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!("omnisharp-{}", release.version);
let binary_path = format!("{version_dir}/OmniSharp");
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,
&version_dir,
match platform {
zed::Os::Mac | zed::Os::Linux => zed::DownloadedFileType::GzipTar,
zed::Os::Windows => zed::DownloadedFileType::Zip,
},
)
.map_err(|e| format!("failed to download file: {e}"))?;
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(OmnisharpBinary {
path: binary_path,
args: binary_args,
})
}
}
impl zed::Extension for CsharpExtension {
fn new() -> Self {
Self {
cached_binary_path: None,
}
}
fn language_server_command(
&mut self,
language_server_id: &zed::LanguageServerId,
worktree: &zed::Worktree,
) -> Result<zed::Command> {
let omnisharp_binary = self.language_server_binary(language_server_id, worktree)?;
Ok(zed::Command {
command: omnisharp_binary.path,
args: omnisharp_binary.args.unwrap_or_else(|| vec!["-lsp".into()]),
env: Default::default(),
})
}
}
zed::register_extension!(CsharpExtension);