Skip to content

Commit

Permalink
Merge pull request #409 from eyakubovich/ey/support-tsx
Browse files Browse the repository at this point in the history
Support for TSX
  • Loading branch information
hendrikvanantwerpen authored Mar 12, 2024
2 parents be64a09 + 805bffd commit c09f746
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 13 deletions.
4 changes: 4 additions & 0 deletions languages/tree-sitter-stack-graphs-typescript/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ tsconfig = "0.1.0"
[dev-dependencies]
anyhow = { version = "1.0" }
tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] }

[build-dependencies]
anyhow = { version = "1.0" }
regex = "1.10.3"
84 changes: 84 additions & 0 deletions languages/tree-sitter-stack-graphs-typescript/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2024, stack-graphs authors.
// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
// ------------------------------------------------------------------------------------------------

use std::path::Path;

use anyhow::{bail, Result};
use regex::Regex;

const TSG_SOURCE: &str = "src/stack-graphs.tsg";
const DIALECTS: [&str; 2] = ["typescript", "tsx"];

/// preprocess the input file, removing lines that are not for the selected dialect
fn preprocess(
input: impl std::io::Read,
mut output: impl std::io::Write,
dialect: &str,
) -> Result<()> {
// Matches: ; #dialect typescript
let directive_start = Regex::new(r";\s*#dialect\s+(\w+)").unwrap();

// Matches: ; #end
let directive_end = Regex::new(r";\s*#end").unwrap();

let no_code = Regex::new(r"^[\s;]+").unwrap();

let input = std::io::read_to_string(input)?;

// If the filter is None or Some(true), the lines are written to the output
let mut filter: Option<bool> = None;

for (mut line_no, line) in input.lines().enumerate() {
// Line numbers are one based
line_no += 1;

if let Some(captures) = directive_start.captures(line) {
if !no_code.is_match(line) {
bail!("Line {line_no}: unexpected code before directive");
}

let directive = captures.get(1).unwrap().as_str();
if !DIALECTS.contains(&directive) {
bail!("Line {line_no}: unknown dialect: {directive}");
}

filter = Some(dialect == directive);
} else if directive_end.is_match(line) {
if !no_code.is_match(line) {
bail!("Line {line_no}: unexpected code before directive end");
}

if filter.is_none() {
bail!("Line {line_no}: unmatched directive end");
}

filter = None;
} else if filter.unwrap_or(true) {
output.write_all(line.as_bytes())?;
}
// a new line is always written so that removed lines are padded to preserve line numbers
output.write(b"\n")?;
}

Ok(())
}

fn main() {
let out_dir = std::env::var_os("OUT_DIR").expect("OUT_DIR is not set");

for dialect in DIALECTS {
let input = std::fs::File::open(TSG_SOURCE).expect("Failed to open stack-graphs.tsg");

let out_filename = Path::new(&out_dir).join(format!("stack-graphs-{dialect}.tsg"));
let output = std::fs::File::create(out_filename).expect("Failed to create output file");

preprocess(input, output, dialect).expect("Failed to preprocess stack-graphs.tsg");
}

println!("cargo:rerun-if-changed={TSG_SOURCE}");
println!("cargo:rerun-if-changed=build.rs");
}
36 changes: 32 additions & 4 deletions languages/tree-sitter-stack-graphs-typescript/rust/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,56 @@
// ------------------------------------------------------------------------------------------------

use anyhow::anyhow;
use clap::Parser;
use clap::{Parser, ValueEnum};
use tree_sitter_stack_graphs::cli::database::default_user_database_path_for_crate;
use tree_sitter_stack_graphs::cli::provided_languages::Subcommands;
use tree_sitter_stack_graphs::loader::{LanguageConfiguration, LoadError};
use tree_sitter_stack_graphs::NoCancellation;

/// Flag to select the dialect of the language
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum Dialect {
Typescript,
TSX,
}

fn main() -> anyhow::Result<()> {
let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration(&NoCancellation)
{
let cli = Cli::parse();
let lc = match language_configuration(cli.dialect) {
Ok(lc) => lc,
Err(err) => {
eprintln!("{}", err.display_pretty());
return Err(anyhow!("Language configuration error"));
}
};
let cli = Cli::parse();
let default_db_path = default_user_database_path_for_crate(env!("CARGO_PKG_NAME"))?;
cli.subcommand.run(default_db_path, vec![lc])
}

fn language_configuration<'a>(dialect: Dialect) -> Result<LanguageConfiguration, LoadError<'a>> {
match dialect {
Dialect::Typescript => {
tree_sitter_stack_graphs_typescript::try_language_configuration_typescript(
&NoCancellation,
)
}
Dialect::TSX => {
tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation)
}
}
}

#[derive(Parser)]
#[clap(about, version)]
pub struct Cli {
#[clap(
short,
long,
value_enum,
default_value_t = Dialect::Typescript,
)]
dialect: Dialect,

#[clap(subcommand)]
subcommand: Subcommands,
}
45 changes: 40 additions & 5 deletions languages/tree-sitter-stack-graphs-typescript/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ pub mod util;
/// The stacks graphs tsg path for this language.
pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg";
/// The stack graphs tsg source for this language
pub const STACK_GRAPHS_TSG_SOURCE: &str = include_str!("../src/stack-graphs.tsg");
pub const STACK_GRAPHS_TSG_TS_SOURCE: &str =
include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg"));
pub const STACK_GRAPHS_TSG_TSX_SOURCE: &str =
include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg"));

/// The stack graphs builtins configuration for this language
pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../src/builtins.cfg");
Expand All @@ -33,11 +36,13 @@ pub const FILE_PATH_VAR: &str = "FILE_PATH";
/// The name of the project name global variable
pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME";

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

pub fn try_language_configuration(
pub fn try_language_configuration_typescript(
cancellation_flag: &dyn CancellationFlag,
) -> Result<LanguageConfiguration, LoadError> {
let mut lc = LanguageConfiguration::from_sources(
Expand All @@ -46,7 +51,37 @@ pub fn try_language_configuration(
None,
vec![String::from("ts")],
STACK_GRAPHS_TSG_PATH.into(),
STACK_GRAPHS_TSG_SOURCE,
STACK_GRAPHS_TSG_TS_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 language_configuration_tsx(
cancellation_flag: &dyn CancellationFlag,
) -> LanguageConfiguration {
try_language_configuration_tsx(cancellation_flag).unwrap_or_else(|err| panic!("{}", err))
}

pub fn try_language_configuration_tsx(
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_TSG_TSX_SOURCE,
Some((
STACK_GRAPHS_BUILTINS_PATH.into(),
STACK_GRAPHS_BUILTINS_SOURCE,
Expand Down
5 changes: 3 additions & 2 deletions languages/tree-sitter-stack-graphs-typescript/rust/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ use tree_sitter_stack_graphs::ci::Tester;
use tree_sitter_stack_graphs::NoCancellation;

fn main() -> anyhow::Result<()> {
let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration(&NoCancellation)
{
let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration_typescript(
&NoCancellation,
) {
Ok(lc) => lc,
Err(err) => {
eprintln!("{}", err.display_pretty());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2665,7 +2665,9 @@ if none @is_async {
(ternary_expression)
(this)
(true)
; #dialect typescript
(type_assertion)
; #end
(unary_expression)
(undefined)
(update_expression)
Expand Down Expand Up @@ -4040,7 +4042,7 @@ if none @is_async {
}



; #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
}

; #end


;; As Expression
Expand Down

0 comments on commit c09f746

Please sign in to comment.