Merge pull request #1098 from zed-industries/cpp

Introduce support for C++
This commit is contained in:
Max Brunsfeld 2022-06-03 10:52:17 -07:00 committed by GitHub
commit 3ce739f759
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 449 additions and 8 deletions

11
Cargo.lock generated
View file

@ -5318,6 +5318,16 @@ dependencies = [
"tree-sitter",
]
[[package]]
name = "tree-sitter-cpp"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a869e3c5cef4e5db4e9ab16a8dc84d73010e60ada14cdc60d2f6d8aed17779d"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-json"
version = "0.19.0"
@ -6030,6 +6040,7 @@ dependencies = [
"toml",
"tree-sitter",
"tree-sitter-c",
"tree-sitter-cpp",
"tree-sitter-json 0.20.0",
"tree-sitter-markdown",
"tree-sitter-rust",

View file

@ -77,7 +77,8 @@ pub trait LspAdapter: 'static + Send + Sync {
container_dir: PathBuf,
) -> BoxFuture<'static, Result<PathBuf>>;
fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option<PathBuf>>;
fn process_diagnostics(&self, diagnostics: &mut lsp::PublishDiagnosticsParams);
fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
fn label_for_completion(&self, _: &lsp::CompletionItem, _: &Language) -> Option<CodeLabel> {
None

View file

@ -88,6 +88,7 @@ tiny_http = "0.8"
toml = "0.5"
tree-sitter = "0.20.6"
tree-sitter-c = "0.20.1"
tree-sitter-cpp = "0.20.0"
tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json", rev = "137e1ce6a02698fc246cdb9c6b886ed1de9a1ed8" }
tree-sitter-rust = "0.20.1"
tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" }

View file

@ -22,6 +22,11 @@ pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegi
tree_sitter_c::language(),
Some(Arc::new(c::CLspAdapter) as Arc<dyn LspAdapter>),
),
(
"cpp",
tree_sitter_cpp::language(),
Some(Arc::new(c::CLspAdapter) as Arc<dyn LspAdapter>),
),
(
"json",
tree_sitter_json::language(),

View file

@ -106,5 +106,139 @@ impl super::LspAdapter for CLspAdapter {
.boxed()
}
fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
fn label_for_completion(
&self,
completion: &lsp::CompletionItem,
language: &Language,
) -> Option<CodeLabel> {
let label = completion
.label
.strip_prefix("")
.unwrap_or(&completion.label)
.trim();
match completion.kind {
Some(lsp::CompletionItemKind::FIELD) if completion.detail.is_some() => {
let detail = completion.detail.as_ref().unwrap();
let text = format!("{} {}", detail, label);
let source = Rope::from(format!("struct S {{ {} }}", text).as_str());
let runs = language.highlight_text(&source, 11..11 + text.len());
return Some(CodeLabel {
filter_range: detail.len() + 1..text.len(),
text,
runs,
});
}
Some(lsp::CompletionItemKind::CONSTANT | lsp::CompletionItemKind::VARIABLE)
if completion.detail.is_some() =>
{
let detail = completion.detail.as_ref().unwrap();
let text = format!("{} {}", detail, label);
let runs = language.highlight_text(&Rope::from(text.as_str()), 0..text.len());
return Some(CodeLabel {
filter_range: detail.len() + 1..text.len(),
text,
runs,
});
}
Some(lsp::CompletionItemKind::FUNCTION | lsp::CompletionItemKind::METHOD)
if completion.detail.is_some() =>
{
let detail = completion.detail.as_ref().unwrap();
let text = format!("{} {}", detail, label);
let runs = language.highlight_text(&Rope::from(text.as_str()), 0..text.len());
return Some(CodeLabel {
filter_range: detail.len() + 1..text.rfind('(').unwrap_or(text.len()),
text,
runs,
});
}
Some(kind) => {
let highlight_name = match kind {
lsp::CompletionItemKind::STRUCT
| lsp::CompletionItemKind::INTERFACE
| lsp::CompletionItemKind::CLASS
| lsp::CompletionItemKind::ENUM => Some("type"),
lsp::CompletionItemKind::ENUM_MEMBER => Some("variant"),
lsp::CompletionItemKind::KEYWORD => Some("keyword"),
lsp::CompletionItemKind::VALUE | lsp::CompletionItemKind::CONSTANT => {
Some("constant")
}
_ => None,
};
if let Some(highlight_id) = language
.grammar()
.and_then(|g| g.highlight_id_for_name(highlight_name?))
{
let mut label = CodeLabel::plain(label.to_string(), None);
label.runs.push((
0..label.text.rfind('(').unwrap_or(label.text.len()),
highlight_id,
));
return Some(label);
}
}
_ => {}
}
Some(CodeLabel::plain(label.to_string(), None))
}
fn label_for_symbol(
&self,
name: &str,
kind: lsp::SymbolKind,
language: &Language,
) -> Option<CodeLabel> {
let (text, filter_range, display_range) = match kind {
lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => {
let text = format!("void {} () {{}}", name);
let filter_range = 0..name.len();
let display_range = 5..5 + name.len();
(text, filter_range, display_range)
}
lsp::SymbolKind::STRUCT => {
let text = format!("struct {} {{}}", name);
let filter_range = 7..7 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::ENUM => {
let text = format!("enum {} {{}}", name);
let filter_range = 5..5 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::INTERFACE | lsp::SymbolKind::CLASS => {
let text = format!("class {} {{}}", name);
let filter_range = 6..6 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::CONSTANT => {
let text = format!("const int {} = 0;", name);
let filter_range = 10..10 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::MODULE => {
let text = format!("namespace {} {{}}", name);
let filter_range = 10..10 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::TYPE_PARAMETER => {
let text = format!("typename {} {{}};", name);
let filter_range = 9..9 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
_ => return None,
};
Some(CodeLabel {
runs: language.highlight_text(&text.as_str().into(), display_range.clone()),
text: text[display_range].to_string(),
filter_range,
})
}
}

View file

@ -1,5 +1,5 @@
name = "C"
path_suffixes = ["c", "h"]
path_suffixes = ["c"]
line_comment = "// "
autoclose_before = ";:.,=}])>"
brackets = [

View file

@ -75,7 +75,6 @@
(comment) @comment
(null) @constant
(number_literal) @number
[

View file

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

View file

@ -0,0 +1,11 @@
name = "C++"
path_suffixes = ["cc", "cpp", "h", "hpp"]
line_comment = "// "
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 },
{ start = "/*", end = " */", close = true, newline = false },
]

View file

@ -0,0 +1,158 @@
(call_expression
function: (qualified_identifier
name: (identifier) @function))
(call_expression
function: (identifier) @function)
(call_expression
function: (field_expression
field: (field_identifier) @function))
(preproc_function_def
name: (identifier) @function.special)
(template_function
name: (identifier) @function)
(template_method
name: (field_identifier) @function)
(function_declarator
declarator: (identifier) @function)
(function_declarator
declarator: (qualified_identifier
name: (identifier) @function))
(function_declarator
declarator: (field_identifier) @function)
((namespace_identifier) @type
(#match? @type "^[A-Z]"))
(auto) @type
(type_identifier) @type
(identifier) @variable
((identifier) @constant
(#match? @constant "^[A-Z][A-Z\\d_]*$"))
(field_identifier) @property
(statement_identifier) @label
(this) @variable.builtin
[
"break"
"case"
"catch"
"class"
"co_await"
"co_return"
"co_yield"
"const"
"constexpr"
"continue"
"default"
"delete"
"do"
"else"
"enum"
"explicit"
"extern"
"final"
"for"
"friend"
"if"
"if"
"inline"
"mutable"
"namespace"
"new"
"noexcept"
"override"
"private"
"protected"
"public"
"return"
"sizeof"
"static"
"struct"
"switch"
"template"
"throw"
"try"
"typedef"
"typename"
"union"
"using"
"virtual"
"volatile"
"while"
(primitive_type)
(type_qualifier)
] @keyword
[
"#define"
"#elif"
"#else"
"#endif"
"#if"
"#ifdef"
"#ifndef"
"#include"
(preproc_directive)
] @keyword
(comment) @comment
[
(true)
(false)
(null)
(nullptr)
] @constant
(number_literal) @number
[
(string_literal)
(system_lib_string)
(char_literal)
(raw_string_literal)
] @string
[
"."
";"
] @punctuation.delimiter
[
"{"
"}"
"("
")"
"["
"]"
] @punctuation.bracket
[
"--"
"-"
"-="
"->"
"="
"!="
"*"
"&"
"&&"
"+"
"++"
"+="
"<"
"=="
">"
"||"
] @operator

View file

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

View file

@ -0,0 +1,101 @@
(preproc_def
"#define" @context
name: (_) @name) @item
(preproc_function_def
"#define" @context
name: (_) @name
parameters: (preproc_params
"(" @context
")" @context)) @item
(type_definition
"typedef" @context
declarator: (_) @name) @item
(struct_specifier
"struct" @context
name: (_) @name) @item
(class_specifier
"class" @context
name: (_) @name) @item
(enum_specifier
"enum" @context
name: (_) @name) @item
(enumerator
name: (_) @name) @item
(declaration
(storage_class_specifier) @context
(type_qualifier)? @context
type: (_) @context
declarator: (init_declarator
declarator: (_) @name)) @item
(function_definition
(type_qualifier)? @context
type: (_)? @context
declarator: [
(function_declarator
declarator: (_) @name
parameters: (parameter_list
"(" @context
")" @context))
(pointer_declarator
"*" @context
declarator: (function_declarator
declarator: (_) @name
parameters: (parameter_list
"(" @context
")" @context)))
]
(type_qualifier)? @context) @item
(declaration
(type_qualifier)? @context
type: (_)? @context
declarator: [
(field_identifier) @name
(pointer_declarator
"*" @context
declarator: (field_identifier) @name)
(function_declarator
declarator: (_) @name
parameters: (parameter_list
"(" @context
")" @context))
(pointer_declarator
"*" @context
declarator: (function_declarator
declarator: (_) @name
parameters: (parameter_list
"(" @context
")" @context)))
]
(type_qualifier)? @context) @item
(field_declaration
(type_qualifier)? @context
type: (_) @context
declarator: [
(field_identifier) @name
(pointer_declarator
"*" @context
declarator: (field_identifier) @name)
(function_declarator
declarator: (_) @name
parameters: (parameter_list
"(" @context
")" @context))
(pointer_declarator
"*" @context
declarator: (function_declarator
declarator: (_) @name
parameters: (parameter_list
"(" @context
")" @context)))
]
(type_qualifier)? @context) @item

View file

@ -120,8 +120,6 @@ impl LspAdapter for JsonLspAdapter {
.boxed()
}
fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
"provideFormatter": true

View file

@ -113,8 +113,6 @@ impl LspAdapter for TypeScriptLspAdapter {
.boxed()
}
fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
fn label_for_completion(
&self,
item: &lsp::CompletionItem,

View file

@ -74,6 +74,20 @@ fn main() {
..Default::default()
},
)
.with_overrides(
"C",
settings::LanguageOverride {
tab_size: Some(2),
..Default::default()
},
)
.with_overrides(
"C++",
settings::LanguageOverride {
tab_size: Some(2),
..Default::default()
},
)
.with_overrides(
"Markdown",
settings::LanguageOverride {