Skip to content

Commit fa37d1c

Browse files
feat(cpp): introduce C++ parser
1 parent 9238fc1 commit fa37d1c

34 files changed

Lines changed: 2070 additions & 0 deletions

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ titlecase = "3.3.0"
5656
tree-sitter = "0.23.0"
5757
tree-sitter-c = "0.23.1"
5858
tree-sitter-c-sharp = "0.23.0"
59+
tree-sitter-cpp = "0.23.0"
5960
tree-sitter-go = "0.23.1"
6061
tree-sitter-python = "0.23.2"
6162
tree-sitter-rust = "0.23.0"

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,34 @@ int main(void) {
11541154
}
11551155
```
11561156
1157+
###### Rename class.
1158+
1159+
You can remove the unnecessary prefix from structure/class fields:
1160+
1161+
```cpp file=class.cpp
1162+
class Class {
1163+
int _field;
1164+
const char *_value;
1165+
std::string _string;
1166+
}
1167+
```
1168+
1169+
with
1170+
1171+
```bash
1172+
cat class.cpp | srgn --cpp 'field-decl' '\b_' ''
1173+
```
1174+
1175+
which will give
1176+
1177+
```cpp file=output-class.cpp
1178+
class Class {
1179+
int field;
1180+
const char *value;
1181+
std::string string;
1182+
}
1183+
```
1184+
11571185
##### Custom queries
11581186
11591187
Custom queries allow you to create ad-hoc scopes. These might be useful, for example, to
@@ -1565,6 +1593,44 @@ Language scopes:
15651593
15661594
[env: C_QUERY=]
15671595

1596+
--cpp <CPP>
1597+
Scope C++ code using a prepared query.
1598+
1599+
[env: CPP=]
1600+
1601+
Possible values:
1602+
- comments: Comments (single- and multi-line)
1603+
- strings: Strings
1604+
- includes: Includes
1605+
- type-def: Type definitions
1606+
- enum: `enum` definitions
1607+
- struct: `struct` type definitions
1608+
- class: `class` definitions
1609+
- namespace: `namespace` definitions
1610+
- using-namespace: `using` namespace declarations
1611+
- template: `template` declarations
1612+
- field-decl: Field declarations
1613+
- variable: Variable definitions
1614+
- function: All functions usages (declarations and calls)
1615+
- function-def: Function definitions
1616+
- function-decl: Function declaration
1617+
- lambda: Lambda
1618+
- switch: `switch` blocks
1619+
- if: `if` blocks
1620+
- for: `for` blocks
1621+
- while: `while` blocks
1622+
- do: `do` blocks
1623+
- union: `union` blocks
1624+
- try: `try` blocks
1625+
- identifier: Identifier
1626+
- declaration: Declaration
1627+
- call-expression: Call expression
1628+
1629+
--cpp-query <TREE-SITTER-QUERY>
1630+
Scope C++ code using a custom tree-sitter query.
1631+
1632+
[env: CPP_QUERY=]
1633+
15681634
--csharp <CSHARP>
15691635
Scope C# code using a prepared query.
15701636

src/main.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use srgn::actions::{
2424
#[cfg(feature = "symbols")]
2525
use srgn::actions::{Symbols, SymbolsInversion};
2626
use srgn::scoping::langs::c::{CQuery, C};
27+
use srgn::scoping::langs::cpp::{Cpp, CppQuery};
2728
use srgn::scoping::langs::csharp::{CSharp, CSharpQuery};
2829
use srgn::scoping::langs::go::{Go, GoQuery};
2930
use srgn::scoping::langs::hcl::{Hcl, HclQuery};
@@ -832,6 +833,7 @@ fn get_language_scopers(args: &cli::Cli) -> Vec<Box<dyn LanguageScoper>> {
832833
}
833834

834835
handle_language_scope!(c, c_query, CQuery, C);
836+
handle_language_scope!(cpp, cpp_query, CppQuery, Cpp);
835837
handle_language_scope!(csharp, csharp_query, CSharpQuery, CSharp);
836838
handle_language_scope!(hcl, hcl_query, HclQuery, Hcl);
837839
handle_language_scope!(go, go_query, GoQuery, Go);
@@ -939,6 +941,7 @@ mod cli {
939941
use clap::{ArgAction, Command, CommandFactory, Parser};
940942
use clap_complete::{generate, Generator, Shell};
941943
use srgn::scoping::langs::c::{CustomCQuery, PreparedCQuery};
944+
use srgn::scoping::langs::cpp::{CustomCppQuery, PreparedCppQuery};
942945
use srgn::scoping::langs::csharp::{CustomCSharpQuery, PreparedCSharpQuery};
943946
use srgn::scoping::langs::go::{CustomGoQuery, PreparedGoQuery};
944947
use srgn::scoping::langs::hcl::{CustomHclQuery, PreparedHclQuery};
@@ -1230,6 +1233,8 @@ mod cli {
12301233
#[command(flatten)]
12311234
pub c: Option<CScope>,
12321235
#[command(flatten)]
1236+
pub cpp: Option<CppScope>,
1237+
#[command(flatten)]
12331238
pub csharp: Option<CSharpScope>,
12341239
#[command(flatten)]
12351240
pub go: Option<GoScope>,
@@ -1255,6 +1260,18 @@ mod cli {
12551260
pub c_query: Vec<CustomCQuery>,
12561261
}
12571262

1263+
#[derive(Parser, Debug, Clone)]
1264+
#[group(required = false, multiple = false)]
1265+
pub struct CppScope {
1266+
/// Scope C++ code using a prepared query.
1267+
#[arg(long, env, verbatim_doc_comment)]
1268+
pub cpp: Vec<PreparedCppQuery>,
1269+
1270+
/// Scope C++ code using a custom tree-sitter query.
1271+
#[arg(long, env, verbatim_doc_comment, value_name = TREE_SITTER_QUERY_VALUE_NAME)]
1272+
pub cpp_query: Vec<CustomCppQuery>,
1273+
}
1274+
12581275
#[derive(Parser, Debug, Clone)]
12591276
#[group(required = false, multiple = false)]
12601277
pub struct CSharpScope {

src/scoping/langs/cpp.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use std::fmt::Debug;
2+
use std::str::FromStr;
3+
4+
use clap::ValueEnum;
5+
use tree_sitter::QueryError;
6+
7+
use super::{CodeQuery, Language, LanguageScoper, TSLanguage, TSQuery};
8+
use crate::find::Find;
9+
10+
/// The C++ language.
11+
pub type Cpp = Language<CppQuery>;
12+
/// A query for C++.
13+
pub type CppQuery = CodeQuery<CustomCppQuery, PreparedCppQuery>;
14+
15+
/// Prepared tree-sitter queries for C++.
16+
#[derive(Debug, Clone, Copy, ValueEnum)]
17+
pub enum PreparedCppQuery {
18+
/// Comments (single- and multi-line).
19+
Comments,
20+
/// Strings.
21+
Strings,
22+
/// Includes.
23+
Includes,
24+
/// Type definitions.
25+
TypeDef,
26+
/// `enum` definitions.
27+
Enum,
28+
/// `struct` type definitions.
29+
Struct,
30+
/// `class` definitions.
31+
Class,
32+
/// `namespace` definitions.
33+
Namespace,
34+
/// `using` namespace declarations.
35+
UsingNamespace,
36+
/// `template` declarations.
37+
Template,
38+
/// Field declarations.
39+
FieldDecl,
40+
/// Variable definitions.
41+
Variable,
42+
/// All functions usages (declarations and calls).
43+
Function,
44+
/// Function definitions.
45+
FunctionDef,
46+
/// Function declaration.
47+
FunctionDecl,
48+
/// Lambda
49+
Lambda,
50+
/// `switch` blocks.
51+
Switch,
52+
/// `if` blocks.
53+
If,
54+
/// `for` blocks.
55+
For,
56+
/// `while` blocks.
57+
While,
58+
/// `do` blocks.
59+
Do,
60+
/// `union` blocks.
61+
Union,
62+
/// `try` blocks.
63+
Try,
64+
/// Identifier.
65+
Identifier,
66+
/// Declaration.
67+
Declaration,
68+
/// Call expression.
69+
CallExpression,
70+
}
71+
72+
impl From<PreparedCppQuery> for TSQuery {
73+
fn from(value: PreparedCppQuery) -> Self {
74+
Self::new(
75+
&Cpp::lang(),
76+
match value {
77+
PreparedCppQuery::Comments => "(comment) @comment",
78+
PreparedCppQuery::Strings => "[(string_literal) (system_lib_string)] @string",
79+
PreparedCppQuery::Includes => "(preproc_include) @include",
80+
PreparedCppQuery::TypeDef => "(type_definition) @typedef",
81+
PreparedCppQuery::Enum => "(enum_specifier) @enum",
82+
PreparedCppQuery::Struct => "(struct_specifier) @struct",
83+
PreparedCppQuery::Class => "(class_specifier) @class",
84+
PreparedCppQuery::Namespace => "(namespace_definition) @namespace",
85+
PreparedCppQuery::UsingNamespace => "(using_declaration) @using",
86+
PreparedCppQuery::Template => "(template_declaration) @template",
87+
PreparedCppQuery::FieldDecl => "(field_declaration) @field_decl",
88+
PreparedCppQuery::Variable => "(declaration) @var",
89+
PreparedCppQuery::Function => {
90+
"[(function_declarator (identifier)) (call_expression (identifier))] @function"
91+
}
92+
PreparedCppQuery::FunctionDef => "(function_definition) @function_definition",
93+
PreparedCppQuery::FunctionDecl => "(function_declarator) @function_decl",
94+
PreparedCppQuery::Lambda => "(lambda_expression) @lambda",
95+
PreparedCppQuery::Switch => "(switch_statement) @switch",
96+
PreparedCppQuery::If => "(if_statement) @if",
97+
PreparedCppQuery::For => "[(for_statement) (for_range_loop)] @for",
98+
PreparedCppQuery::While => "(while_statement) @while",
99+
PreparedCppQuery::Union => "(union_specifier) @union",
100+
PreparedCppQuery::Try => "(try_statement) @try",
101+
PreparedCppQuery::Do => "(do_statement) @do",
102+
PreparedCppQuery::Identifier => "(identifier) @ident",
103+
PreparedCppQuery::Declaration => "(declaration) @decl",
104+
PreparedCppQuery::CallExpression => "(call_expression) @call",
105+
},
106+
)
107+
.expect("Prepared queries to be valid")
108+
}
109+
}
110+
111+
/// A custom tree-sitter query for C++.
112+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
113+
pub struct CustomCppQuery(String);
114+
115+
impl FromStr for CustomCppQuery {
116+
type Err = QueryError;
117+
118+
fn from_str(s: &str) -> Result<Self, Self::Err> {
119+
match TSQuery::new(&Cpp::lang(), s) {
120+
Ok(_) => Ok(Self(s.to_string())),
121+
Err(e) => Err(e),
122+
}
123+
}
124+
}
125+
126+
impl From<CustomCppQuery> for TSQuery {
127+
fn from(value: CustomCppQuery) -> Self {
128+
Self::new(&Cpp::lang(), &value.0)
129+
.expect("Valid query, as object cannot be constructed otherwise")
130+
}
131+
}
132+
133+
impl LanguageScoper for Cpp {
134+
fn lang() -> TSLanguage {
135+
tree_sitter_cpp::LANGUAGE.into()
136+
}
137+
138+
fn pos_query(&self) -> &TSQuery {
139+
&self.positive_query
140+
}
141+
142+
fn neg_query(&self) -> Option<&TSQuery> {
143+
self.negative_query.as_ref()
144+
}
145+
}
146+
147+
impl Find for Cpp {
148+
fn extensions(&self) -> &'static [&'static str] {
149+
&["cpp", "hpp"]
150+
}
151+
}

src/scoping/langs/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use crate::scoping::{
1818

1919
/// C.
2020
pub mod c;
21+
/// C++.
22+
pub mod cpp;
2123
/// C#.
2224
pub mod csharp;
2325
/// Go.

0 commit comments

Comments
 (0)