Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit d75b47e

Browse files
author
Hendrik van Antwerpen
authored
Merge pull request #155 from github/add-file-analyzers
Add file analyzers
2 parents bca02ae + 1e9c349 commit d75b47e

File tree

7 files changed

+105
-5
lines changed

7 files changed

+105
-5
lines changed

languages/tree-sitter-stack-graphs-typescript/rust/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
66
// ------------------------------------------------------------------------------------------------
77

8+
use tree_sitter_stack_graphs::loader::FileAnalyzers;
89
use tree_sitter_stack_graphs::loader::LanguageConfiguration;
910
use tree_sitter_stack_graphs::CancellationFlag;
11+
use tsconfig::TsConfigAnalyzer;
12+
13+
pub mod tsconfig;
1014

1115
/// The stack graphs tsg source for this language
1216
const STACK_GRAPHS_TSG_SOURCE: &str = include_str!("../src/stack-graphs.tsg");
@@ -25,6 +29,7 @@ pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> Langu
2529
STACK_GRAPHS_TSG_SOURCE,
2630
Some(STACK_GRAPHS_BUILTINS_SOURCE),
2731
Some(STACK_GRAPHS_BUILTINS_CONFIG),
32+
FileAnalyzers::new().add("tsconfig.json".to_string(), TsConfigAnalyzer {}),
2833
cancellation_flag,
2934
)
3035
.unwrap()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// -*- coding: utf-8 -*-
2+
// ------------------------------------------------------------------------------------------------
3+
// Copyright © 2022, stack-graphs authors.
4+
// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
5+
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
6+
// ------------------------------------------------------------------------------------------------
7+
8+
use std::collections::HashMap;
9+
use std::path::Path;
10+
11+
use stack_graphs::arena::Handle;
12+
use stack_graphs::graph::File;
13+
use stack_graphs::graph::StackGraph;
14+
use tree_sitter_stack_graphs::FileAnalyzer;
15+
16+
pub struct TsConfigAnalyzer {}
17+
18+
impl FileAnalyzer for TsConfigAnalyzer {
19+
fn build_stack_graph_into<'a>(
20+
&self,
21+
_graph: &mut StackGraph,
22+
_file: Handle<File>,
23+
_path: &Path,
24+
_source: &str,
25+
_all_paths: &mut dyn Iterator<Item = &'a Path>,
26+
_globals: &HashMap<String, String>,
27+
_cancellation_flag: &dyn tree_sitter_stack_graphs::CancellationFlag,
28+
) -> Result<(), tree_sitter_stack_graphs::LoadError> {
29+
todo!()
30+
}
31+
}

tree-sitter-stack-graphs/src/cli/test.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,26 @@ impl TestArgs {
209209
.with_context(|| format!("Loading builtins into {}", test_path.display()))?;
210210
let mut globals = Variables::new();
211211
for test_fragment in &test.fragments {
212-
let fragment_path = Path::new(test.graph[test_fragment.file].name()).to_path_buf();
213-
if lc.matches_file(&fragment_path, Some(&test_fragment.source)) {
212+
if let Some(fa) = test_fragment
213+
.path
214+
.file_name()
215+
.and_then(|f| lc.special_files.get(&f.to_string_lossy()))
216+
{
217+
let mut all_paths = test.fragments.iter().map(|f| f.path.as_path());
218+
fa.build_stack_graph_into(
219+
&mut test.graph,
220+
test_fragment.file,
221+
&test_fragment.path,
222+
&test_fragment.source,
223+
&mut all_paths,
224+
&test_fragment.globals,
225+
&NoCancellation,
226+
)?;
227+
} else if lc.matches_file(&test_fragment.path, Some(&test_fragment.source)) {
214228
globals.clear();
215229
test_fragment.add_globals_to(&mut globals);
216230
self.build_fragment_stack_graph_into(
217-
&fragment_path,
231+
&test_fragment.path,
218232
&lc.sgl,
219233
test_fragment.file,
220234
&test_fragment.source,
@@ -224,8 +238,8 @@ impl TestArgs {
224238
} else {
225239
return Err(anyhow!(
226240
"Test fragment {} not supported by language of test file {}",
227-
fragment_path.display(),
228-
test_path.display()
241+
test_fragment.path.display(),
242+
test.path.display()
229243
));
230244
}
231245
}

tree-sitter-stack-graphs/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ use stack_graphs::graph::StackGraph;
319319
use std::collections::HashMap;
320320
use std::collections::HashSet;
321321
use std::mem::transmute;
322+
use std::path::Path;
322323
use std::sync::atomic::AtomicUsize;
323324
use std::sync::atomic::Ordering;
324325
use thiserror::Error;
@@ -578,6 +579,7 @@ impl<'a> Builder<'a> {
578579
pub trait CancellationFlag {
579580
fn flag(&self) -> Option<&AtomicUsize>;
580581
}
582+
581583
impl stack_graphs::CancellationFlag for &dyn CancellationFlag {
582584
fn check(&self, at: &'static str) -> Result<(), stack_graphs::CancellationError> {
583585
if self.flag().map_or(0, |f| f.load(Ordering::Relaxed)) != 0 {
@@ -586,6 +588,7 @@ impl stack_graphs::CancellationFlag for &dyn CancellationFlag {
586588
Ok(())
587589
}
588590
}
591+
589592
impl tree_sitter_graph::CancellationFlag for &dyn CancellationFlag {
590593
fn check(&self, at: &'static str) -> Result<(), tree_sitter_graph::CancellationError> {
591594
if self.flag().map_or(0, |f| f.load(Ordering::Relaxed)) != 0 {
@@ -596,6 +599,7 @@ impl tree_sitter_graph::CancellationFlag for &dyn CancellationFlag {
596599
}
597600

598601
pub struct NoCancellation;
602+
599603
impl CancellationFlag for NoCancellation {
600604
fn flag(&self) -> Option<&AtomicUsize> {
601605
None
@@ -933,3 +937,16 @@ impl<'a> Builder<'a> {
933937
}
934938
}
935939
}
940+
941+
pub trait FileAnalyzer {
942+
fn build_stack_graph_into<'a>(
943+
&self,
944+
stack_graph: &mut StackGraph,
945+
file: Handle<File>,
946+
path: &Path,
947+
source: &str,
948+
all_paths: &mut dyn Iterator<Item = &'a Path>,
949+
globals: &HashMap<String, String>,
950+
cancellation_flag: &dyn CancellationFlag,
951+
) -> Result<(), LoadError>;
952+
}

tree-sitter-stack-graphs/src/loader.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::collections::HashMap;
1616
use std::ffi::OsStr;
1717
use std::path::Path;
1818
use std::path::PathBuf;
19+
use std::sync::Arc;
1920
use thiserror::Error;
2021
use tree_sitter::Language;
2122
use tree_sitter_graph::ast::File as TsgFile;
@@ -25,6 +26,7 @@ use tree_sitter_loader::LanguageConfiguration as TSLanguageConfiguration;
2526
use tree_sitter_loader::Loader as TsLoader;
2627

2728
use crate::CancellationFlag;
29+
use crate::FileAnalyzer;
2830
use crate::StackGraphLanguage;
2931

3032
lazy_static! {
@@ -42,6 +44,7 @@ pub struct LanguageConfiguration {
4244
pub file_types: Vec<String>,
4345
pub sgl: StackGraphLanguage,
4446
pub builtins: StackGraph,
47+
pub special_files: FileAnalyzers,
4548
}
4649

4750
impl LanguageConfiguration {
@@ -53,6 +56,7 @@ impl LanguageConfiguration {
5356
tsg_source: &str,
5457
builtins_source: Option<&str>,
5558
builtins_config: Option<&str>,
59+
special_files: FileAnalyzers,
5660
cancellation_flag: &dyn CancellationFlag,
5761
) -> Result<Self, LoadError> {
5862
let sgl = StackGraphLanguage::from_str(language, tsg_source)?;
@@ -78,6 +82,7 @@ impl LanguageConfiguration {
7882
file_types,
7983
sgl,
8084
builtins,
85+
special_files,
8186
})
8287
}
8388

@@ -86,6 +91,28 @@ impl LanguageConfiguration {
8691
}
8792
}
8893

94+
#[derive(Clone, Default)]
95+
pub struct FileAnalyzers {
96+
file_analyzers: HashMap<String, Arc<dyn FileAnalyzer>>,
97+
}
98+
99+
impl FileAnalyzers {
100+
pub fn new() -> Self {
101+
FileAnalyzers {
102+
file_analyzers: HashMap::new(),
103+
}
104+
}
105+
106+
pub fn add(mut self, file_name: String, analyzer: impl FileAnalyzer + 'static) -> Self {
107+
self.file_analyzers.insert(file_name, Arc::new(analyzer));
108+
self
109+
}
110+
111+
pub fn get(&self, file_name: &str) -> Option<&Arc<dyn FileAnalyzer>> {
112+
self.file_analyzers.get(file_name)
113+
}
114+
}
115+
89116
/// A load path specifies a file to load from, either as a regular path or relative to the grammar location.
90117
#[derive(Clone, Debug)]
91118
pub enum LoadPath {
@@ -415,6 +442,7 @@ impl PathLoader {
415442
file_types: language.file_types,
416443
sgl,
417444
builtins,
445+
special_files: FileAnalyzers::new(),
418446
};
419447
self.cache.push((language.language, lc));
420448

tree-sitter-stack-graphs/src/test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ pub struct Test {
126126
#[derive(Debug, Clone)]
127127
pub struct TestFragment {
128128
pub file: Handle<File>,
129+
pub path: PathBuf,
129130
pub source: String,
130131
pub assertions: Vec<Assertion>,
131132
pub globals: HashMap<String, String>,
@@ -167,6 +168,7 @@ impl Test {
167168
.for_each(|_| line_files.push(Some(file)));
168169
fragments.push(TestFragment {
169170
file,
171+
path: current_path,
170172
source: current_source,
171173
assertions: Vec::new(),
172174
globals: current_globals,
@@ -206,6 +208,7 @@ impl Test {
206208
(line_files.len()..line_count).for_each(|_| line_files.push(Some(file)));
207209
fragments.push(TestFragment {
208210
file,
211+
path: current_path,
209212
source: current_source,
210213
assertions: Vec::new(),
211214
globals: current_globals,

tree-sitter-stack-graphs/tests/it/loader.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use lazy_static::lazy_static;
99
use pretty_assertions::assert_eq;
1010
use stack_graphs::graph::StackGraph;
1111
use std::path::PathBuf;
12+
use tree_sitter_stack_graphs::loader::FileAnalyzers;
1213
use tree_sitter_stack_graphs::loader::LanguageConfiguration;
1314
use tree_sitter_stack_graphs::loader::Loader;
1415
use tree_sitter_stack_graphs::NoCancellation;
@@ -33,6 +34,7 @@ fn can_load_from_provided_language_configuration() {
3334
file_types: vec!["py".into()],
3435
sgl,
3536
builtins: StackGraph::new(),
37+
special_files: FileAnalyzers::new(),
3638
};
3739
let mut loader =
3840
Loader::from_language_configurations(vec![lc], None).expect("Expected loader to succeed");

0 commit comments

Comments
 (0)