Skip to content

Commit

Permalink
Support for TSX
Browse files Browse the repository at this point in the history
Support TSX dialect of the TypeScript.
Because the TSX is almost a superset of TypeScript,
it makes sense to reuse the .tsg file. However it
requires a bit of preprocessing to handle the differences.
  • Loading branch information
eyakubovich committed Mar 10, 2024
1 parent be64a09 commit 88bc170
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 3 deletions.
2 changes: 2 additions & 0 deletions languages/tree-sitter-stack-graphs-typescript/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ lsp = ["tree-sitter-stack-graphs/lsp"]

[dependencies]
anyhow = { version = "1.0", optional = true }
askama = "0.12.1"
clap = { version = "4", optional = true }
glob = "0.3"
lazy_static = "1.4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
stack-graphs = { version = "0.13", path = "../../stack-graphs" }
Expand Down
9 changes: 9 additions & 0 deletions languages/tree-sitter-stack-graphs-typescript/askama.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[general]
# Directories to search for templates, relative to the crate root.
dirs = ["src"]
# Unless you add a `-` in a block, whitespace characters won't be trimmed.
whitespace = "preserve"

[[escaper]]
path = "::askama::Text"
extensions = ["tsg"]
56 changes: 55 additions & 1 deletion languages/tree-sitter-stack-graphs-typescript/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
// ------------------------------------------------------------------------------------------------

use std::path::PathBuf;
use std::borrow::Cow;

use askama::Template;
use lazy_static::lazy_static;
use tree_sitter_stack_graphs::loader::LanguageConfiguration;
use tree_sitter_stack_graphs::loader::LoadError;
use tree_sitter_stack_graphs::CancellationFlag;
Expand Down Expand Up @@ -33,10 +38,25 @@ pub const FILE_PATH_VAR: &str = "FILE_PATH";
/// The name of the project name global variable
pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME";

lazy_static! {
static ref STACK_GRAPHS_TS_TSG_SOURCE: String = preprocess_tsg("typescript").unwrap();
static ref STACK_GRAPHS_TSX_TSG_SOURCE: String = preprocess_tsg("tsx").unwrap();
}

#[derive(Template)]
#[template(path = "stack-graphs.tsg")]
struct TsgTemplate<'a> {
dialect: &'a str,
}

pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration {
try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err))
}

pub fn tsx_language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration {
try_tsx_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err))
}

pub fn try_language_configuration(
cancellation_flag: &dyn CancellationFlag,
) -> Result<LanguageConfiguration, LoadError> {
Expand All @@ -46,7 +66,31 @@ pub fn try_language_configuration(
None,
vec![String::from("ts")],
STACK_GRAPHS_TSG_PATH.into(),
STACK_GRAPHS_TSG_SOURCE,
&STACK_GRAPHS_TS_TSG_SOURCE,
Some((
STACK_GRAPHS_BUILTINS_PATH.into(),
STACK_GRAPHS_BUILTINS_SOURCE,
)),
Some(STACK_GRAPHS_BUILTINS_CONFIG),
cancellation_flag,
)?;
lc.special_files
.add("tsconfig.json".to_string(), TsConfigAnalyzer {})
.add("package.json".to_string(), NpmPackageAnalyzer {});
lc.no_similar_paths_in_file = true;
Ok(lc)
}

pub fn try_tsx_language_configuration(
cancellation_flag: &dyn CancellationFlag,
) -> Result<LanguageConfiguration, LoadError> {
let mut lc = LanguageConfiguration::from_sources(
tree_sitter_typescript::language_tsx(),
Some(String::from("source.tsx")),
None,
vec![String::from("tsx")],
STACK_GRAPHS_TSG_PATH.into(),
&STACK_GRAPHS_TSX_TSG_SOURCE,
Some((
STACK_GRAPHS_BUILTINS_PATH.into(),
STACK_GRAPHS_BUILTINS_SOURCE,
Expand All @@ -60,3 +104,13 @@ pub fn try_language_configuration(
lc.no_similar_paths_in_file = true;
Ok(lc)
}

fn preprocess_tsg(dialect: &'static str) -> Result<String, LoadError<'static>> {
let tmpl = TsgTemplate{ dialect };
tmpl.render()
.map_err(|err| LoadError::PreprocessorError {
inner: err.to_string(),
tsg_path: PathBuf::from(STACK_GRAPHS_TSG_PATH),
tsg: Cow::from(STACK_GRAPHS_TSG_SOURCE),
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -2665,7 +2665,9 @@ if none @is_async {
(ternary_expression)
(this)
(true)
{% if dialect == "typescript" -%}
(type_assertion)
{% endif -%}
(unary_expression)
(undefined)
(update_expression)
Expand Down Expand Up @@ -4040,7 +4042,7 @@ if none @is_async {
}



{% if dialect == "typescript" -%}
;; Type Assertion

; (type_assertion
Expand All @@ -4055,7 +4057,7 @@ if none @is_async {
; propagate lexical scope
edge @expr.lexical_scope -> @type_assert.lexical_scope
}

{% endif -%}


;; As Expression
Expand Down
6 changes: 6 additions & 0 deletions tree-sitter-stack-graphs/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,12 @@ pub enum LoadError<'a> {
},
#[error(transparent)]
TreeSitter(anyhow::Error),
#[error("Preprocessor error: {inner}")]
PreprocessorError {
inner: String,
tsg_path: PathBuf,
tsg: Cow<'a, str>,
}
}

impl LoadError<'_> {
Expand Down

0 comments on commit 88bc170

Please sign in to comment.