Skip to content

Commit

Permalink
feat: Implement string interpolation handling
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpovel committed Nov 30, 2023
1 parent 37de0d4 commit 2f37b2e
Show file tree
Hide file tree
Showing 7 changed files with 596 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/scoping/langs/csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl From<CustomCSharpQuery> for TSQuery {

impl Scoper for CSharp {
fn scope<'viewee>(&self, input: &'viewee str) -> ROScopes<'viewee> {
self.scope_via_query(input)
ROScopes::from_raw_ranges(input, Self::scope_via_query(&mut self.query(), input))
}
}

Expand Down
70 changes: 51 additions & 19 deletions src/scoping/langs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::{ROScopes, Scoper};
use super::Scoper;
#[cfg(doc)]
use crate::scoping::scope::Scope::{In, Out};
use crate::scoping::scope::{merge, subtract};
use log::{debug, trace};
use std::str::FromStr;
use std::{ops::Range, str::FromStr};
pub use tree_sitter::{
Language as TSLanguage, Parser as TSParser, Query as TSQuery, QueryCursor as TSQueryCursor,
};
Expand Down Expand Up @@ -82,34 +83,65 @@ pub trait LanguageScoper: Scoper {
/// Scope the given input using the language's query.
///
/// In principle, this is the same as [`Scoper::scope`].
fn scope_via_query<'viewee>(&self, input: &'viewee str) -> ROScopes<'viewee> {
let ranges = {
// tree-sitter is about incremental parsing, which we don't use here
let old_tree = None;
fn scope_via_query(query: &mut TSQuery, input: &str) -> Vec<Range<usize>> {
// tree-sitter is about incremental parsing, which we don't use here
let old_tree = None;

trace!("Parsing into AST: {:?}", input);
trace!("Parsing into AST: {:?}", input);

let tree = Self::parser()
.parse(input, old_tree)
.expect("No language set in parser, or other unrecoverable error");
let tree = Self::parser()
.parse(input, old_tree)
.expect("No language set in parser, or other unrecoverable error");

let root = tree.root_node();
debug!(
"S expression of parsed source code is: {:?}",
root.to_sexp()
);
let root = tree.root_node();
debug!(
"S expression of parsed source code is: {:?}",
root.to_sexp()
);

let run = |query: &mut TSQuery| {
trace!("Running query: {:?}", query);

let mut qc = TSQueryCursor::new();
let query = self.query();
let matches = qc.matches(&query, root, input.as_bytes());
let matches = qc.matches(query, root, input.as_bytes());

let ranges = matches
.flat_map(|query_match| query_match.captures)
.map(|capture| capture.node.byte_range());

ranges.collect()
let res = ranges.collect();
trace!("Querying yielded ranges: {:?}", res);

res
};

ROScopes::from_raw_ranges(input, ranges)
let ranges = run(query);

let has_ignore = query.capture_names().iter().any(|name| name == "IGNORE");

// Merge, because tree-sitter queries with multiple captures will return them in
// some mixed order (not ordered, and not merged), but we later rely on cleanly
// ordered, non-overlapping ranges (a bit unfortunate we have to know about that
// remote part over here).
merge(if has_ignore {
let ignored_ranges = {
let capture_names = query.capture_names().to_owned();
for name in capture_names {
if name != "IGNORE" {
query.disable_capture(&name);
}
}

debug!("Query has captures to ignore: running additional query");
run(query)
};

let res = subtract(ranges, &ignored_ranges);
debug!("Ranges cleaned up after subtracting ignores: {:?}", res);

res
} else {
ranges
})
}
}
3 changes: 2 additions & 1 deletion src/scoping/langs/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ impl From<CustomPythonQuery> for TSQuery {

impl Scoper for Python {
fn scope<'viewee>(&self, input: &'viewee str) -> ROScopes<'viewee> {
self.scope_via_query(input)
// self.scope_via_query(input)
ROScopes::from_raw_ranges(input, Self::scope_via_query(&mut self.query(), input))
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/scoping/langs/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ impl From<PremadeTypeScriptQuery> for TSQuery {
match value {
PremadeTypeScriptQuery::Comments => "(comment) @comment",
PremadeTypeScriptQuery::Strings => {
// (template_string)
r#"
[
(template_string)
(template_string (template_substitution) @IGNORE)
(string)
]
@string
Expand Down Expand Up @@ -63,7 +64,9 @@ impl From<CustomTypeScriptQuery> for TSQuery {

impl Scoper for TypeScript {
fn scope<'viewee>(&self, input: &'viewee str) -> ROScopes<'viewee> {
self.scope_via_query(input)
let ranges = Self::scope_via_query(&mut self.query(), input);

ROScopes::from_raw_ranges(input, ranges)
}
}

Expand Down
Loading

0 comments on commit 2f37b2e

Please sign in to comment.