Skip to content

Commit

Permalink
feat: create records for translation and i18n usage of each parsed mo…
Browse files Browse the repository at this point in the history
…dule
  • Loading branch information
wtlin1228 committed Oct 10, 2024
1 parent 27ab333 commit c393e3d
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 14 deletions.
72 changes: 66 additions & 6 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use dt_core::{
scheduler::ParserCandidateScheduler,
};
use std::{
collections::{HashMap, HashSet},
fs::File,
io::{prelude::*, BufReader},
path::PathBuf,
Expand Down Expand Up @@ -340,7 +341,10 @@ impl Project {
Ok(())
}

pub fn add_module(&self, symbol_dependency: &SymbolDependency) -> anyhow::Result<()> {
pub fn add_module(
&self,
symbol_dependency: &SymbolDependency,
) -> anyhow::Result<models::Module> {
let module = self.project.add_module(
&self.db.conn,
&self.remove_prefix(&symbol_dependency.canonical_path),
Expand All @@ -351,6 +355,46 @@ impl Project {
self.handle_default_export(&module, symbol_dependency)?;
self.handle_re_export_star_from(&module, symbol_dependency)?;

Ok(module)
}

pub fn add_translation(
&self,
translation_json: &HashMap<String, String>,
) -> anyhow::Result<()> {
for (key, value) in translation_json.iter() {
self.project.add_translation(&self.db.conn, key, value)?;
}
Ok(())
}

pub fn add_i18n_usage(
&self,
module: &models::Module,
i18n_usage: &HashMap<String, HashSet<String>>,
) -> anyhow::Result<()> {
for (symbol_name, i18n_keys) in i18n_usage.iter() {
let symbol = module
.get_symbol(
&self.db.conn,
models::SymbolVariant::LocalVariable,
&symbol_name,
)
.context(format!(
"try to add i18n keys for symbol {}, but symbol doesn't exist",
symbol_name,
))?;
for key in i18n_keys.iter() {
let translation =
self.project
.get_translation(&self.db.conn, key)
.context(format!(
"try to add translation for symbol {}, but translation {} doesn't exist",
symbol_name, key
))?;
models::TranslationUsage::create(&self.db.conn, &translation, &symbol)?;
}
}
Ok(())
}
}
Expand All @@ -359,23 +403,39 @@ fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
let project_root = PathBuf::from(&cli.input).to_canonical_string()?;
let project = Project::new(&project_root, "./database/1010.db3")?;
let translation_json = File::open(&cli.translation_path)?;
let translation_json_reader = BufReader::new(translation_json);
let translation_file = File::open(&cli.translation_path)?;
let translation_json_reader = BufReader::new(translation_file);
let mut scheduler = ParserCandidateScheduler::new(&project_root);
let mut depend_on_graph = DependOnGraph::new(&project_root);
let mut symbol_to_route = SymbolToRoutes::new();
let mut i18n_to_symbol = I18nToSymbol::new();

let translation_json: HashMap<String, String> =
serde_json::from_reader(translation_json_reader)?;
project
.add_translation(&translation_json)
.context("add translation to project")?;

loop {
match scheduler.get_one_candidate() {
Some(c) => {
let module_src = c.to_str().context(format!("to_str() failed: {:?}", c))?;
let module_ast = Input::Path(module_src).get_module_ast()?;
let symbol_dependency = collect_symbol_dependency(&module_ast, module_src)?;
i18n_to_symbol.collect_i18n_usage(module_src, &module_ast)?;
let i18n_usage = i18n_to_symbol.collect_i18n_usage(module_src, &module_ast)?;
symbol_to_route.collect_route_dependency(&module_ast, &symbol_dependency)?;

project.add_module(&symbol_dependency)?;
let module = project.add_module(&symbol_dependency).context(format!(
"add module {} to project",
symbol_dependency.canonical_path
))?;
project
.add_i18n_usage(&module, &i18n_usage)
.context(format!(
"add i18n usage of module {} to project",
symbol_dependency.canonical_path
))?;

depend_on_graph.add_symbol_dependency(symbol_dependency)?;
scheduler.mark_candidate_as_parsed(c);
}
Expand All @@ -385,7 +445,7 @@ fn main() -> anyhow::Result<()> {

let portable = Portable::new(
project_root.to_owned(),
serde_json::from_reader(translation_json_reader)?,
translation_json,
i18n_to_symbol.table,
symbol_to_route.table,
UsedByGraph::from(&depend_on_graph),
Expand Down
81 changes: 76 additions & 5 deletions crates/dt_database/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ impl Project {
Err(_) => self.add_module(conn, path),
}
}

pub fn add_translation(
&self,
conn: &Connection,
key: &str,
value: &str,
) -> anyhow::Result<Translation> {
Translation::create(conn, self, key, value)
}

pub fn get_translation(&self, conn: &Connection, key: &str) -> anyhow::Result<Translation> {
Translation::retrieve(conn, self, key)
}
}

#[derive(Debug)]
Expand Down Expand Up @@ -119,6 +132,15 @@ impl Module {
Symbol::create(conn, self, variant, name)
}

pub fn get_symbol(
&self,
conn: &Connection,
variant: SymbolVariant,
name: &str,
) -> anyhow::Result<Symbol> {
Symbol::retrieve(conn, self, variant, name)
}

/// single thread only: retrieve then create
pub fn get_or_create_symbol(
&self,
Expand Down Expand Up @@ -291,6 +313,7 @@ impl SymbolDependency {
#[derive(Debug)]
pub struct Translation {
pub id: usize,
pub project_id: usize,
pub key: String,
pub value: String,
}
Expand All @@ -299,9 +322,10 @@ impl Model for Translation {
fn table() -> String {
"
translation (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT NOT NULL,
value TEXT NOT NULL
id INTEGER PRIMARY KEY AUTOINCREMENT,
project_id INTEGER REFERENCES project(id) ON DELETE CASCADE,
key TEXT NOT NULL,
value TEXT NOT NULL
)
"
.to_string()
Expand All @@ -312,10 +336,39 @@ impl Translation {
pub fn from_row(row: &Row) -> rusqlite::Result<Self> {
Ok(Self {
id: row.get(0)?,
key: row.get(1)?,
value: row.get(2)?,
project_id: row.get(1)?,
key: row.get(2)?,
value: row.get(3)?,
})
}

/// single thread only: last_insert_rowid()
pub fn create(
conn: &Connection,
project: &Project,
key: &str,
value: &str,
) -> anyhow::Result<Self> {
conn.execute(
"INSERT INTO translation (project_id, key, value) VALUES (?1, ?2, ?3)",
params![project.id, key, value],
)?;
let translation = conn.query_row(
"SELECT * FROM translation WHERE id=last_insert_rowid()",
(),
Self::from_row,
)?;
Ok(translation)
}

pub fn retrieve(conn: &Connection, project: &Project, key: &str) -> anyhow::Result<Self> {
let translation = conn.query_row(
"SELECT * FROM translation WHERE (project_id, key) = (?1, ?2)",
params![project.id, key],
Self::from_row,
)?;
Ok(translation)
}
}

// Join Table
Expand Down Expand Up @@ -347,6 +400,24 @@ impl TranslationUsage {
symbol_id: row.get(2)?,
})
}

/// single thread only: last_insert_rowid()
pub fn create(
conn: &Connection,
translation: &Translation,
symbol: &Symbol,
) -> anyhow::Result<Self> {
conn.execute(
"INSERT INTO translation_usage (translation_id, symbol_id) VALUES (?1, ?2)",
params![translation.id, symbol.id],
)?;
let translation = conn.query_row(
"SELECT * FROM translation_usage WHERE id=last_insert_rowid()",
(),
Self::from_row,
)?;
Ok(translation)
}
}

#[derive(Debug)]
Expand Down
6 changes: 3 additions & 3 deletions crates/dt_i18n/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ impl I18nToSymbol {
&mut self,
module_path: &str,
module_ast: &Module,
) -> anyhow::Result<()> {
) -> anyhow::Result<HashMap<String, HashSet<String>>> {
let i18n_usage = core::collect_translation(module_ast)?;
for (symbol, i18n_keys) in i18n_usage {
for (symbol, i18n_keys) in i18n_usage.iter() {
for i18n_key in i18n_keys.iter() {
if !self.table.contains_key(i18n_key) {
self.table.insert(i18n_key.to_owned(), HashMap::new());
Expand All @@ -38,6 +38,6 @@ impl I18nToSymbol {
.insert(symbol.to_owned());
}
}
Ok(())
Ok(i18n_usage)
}
}

0 comments on commit c393e3d

Please sign in to comment.