Skip to content

Commit aa82356

Browse files
committed
optimize: reuse template compilation result for typescript
1 parent ca28e89 commit aa82356

File tree

12 files changed

+366
-55
lines changed

12 files changed

+366
-55
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ compact_str = "0.8.0"
1616
cssparser = "0.34.0"
1717
cssparser-color = "0.2.0"
1818
futures = "0.3.31"
19-
glass-easel-template-compiler = "0.15.2"
19+
glass-easel-template-compiler = "0.15.3"
2020
itertools = "0.13.0"
2121
log = "0.4.22"
2222
lsp-server = "0.7.7"

pnpm-lock.yaml

Lines changed: 25 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/context/project.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ use std::{
66

77
use futures::StreamExt;
88
use glass_easel_template_compiler::{
9-
parse::{ParseError, ParseErrorKind, ParseErrorLevel, Template},
10-
TmplGroup,
9+
parse::{ParseError, ParseErrorKind, ParseErrorLevel, Template}, TmplConvertedExpr, TmplGroup
1110
};
1211
use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range};
1312
use tokio::sync::Mutex as AsyncMutex;
1413

1514
use super::{FileLang, ServerContextOptions};
16-
use crate::wxss::{self, StyleSheet};
15+
use crate::wxss::{self, Location, StyleSheet};
1716

1817
#[derive(Debug)]
1918
pub(crate) struct FileContentMetadata {
@@ -110,6 +109,7 @@ pub(crate) struct Project {
110109
file_contents: HashMap<PathBuf, FileContentMetadata>,
111110
json_config_map: HashMap<PathBuf, JsonConfig>,
112111
template_group: TmplGroup,
112+
cached_wxml_converted_expr: HashMap<String, TmplConvertedExpr>,
113113
style_sheet_map: HashMap<PathBuf, StyleSheet>,
114114
enable_other_ss: bool,
115115
}
@@ -121,6 +121,7 @@ impl Default for Project {
121121
file_contents: HashMap::new(),
122122
json_config_map: HashMap::new(),
123123
template_group: TmplGroup::new(),
124+
cached_wxml_converted_expr: HashMap::new(),
124125
style_sheet_map: HashMap::new(),
125126
enable_other_ss: false,
126127
}
@@ -186,6 +187,7 @@ impl Project {
186187
file_contents: HashMap::new(),
187188
json_config_map: HashMap::new(),
188189
template_group: TmplGroup::new(),
190+
cached_wxml_converted_expr: HashMap::new(),
189191
style_sheet_map: HashMap::new(),
190192
enable_other_ss: options.enable_other_ss,
191193
}
@@ -521,6 +523,7 @@ impl Project {
521523
fn cleanup_wxml(&mut self, abs_path: &Path) -> anyhow::Result<()> {
522524
let tmpl_path = self.unix_rel_path_or_fallback(&abs_path);
523525
self.template_group.remove_tmpl(&tmpl_path);
526+
self.cached_wxml_converted_expr.remove(&tmpl_path);
524527
self.file_contents.remove(abs_path);
525528
Ok(())
526529
}
@@ -557,6 +560,37 @@ impl Project {
557560
self.template_group.list_template_trees()
558561
}
559562

563+
pub(crate) fn wxml_converted_expr_release(&mut self, abs_path: &Path) -> bool {
564+
let tmpl_path = self.unix_rel_path_or_fallback(&abs_path);
565+
self.cached_wxml_converted_expr.remove(&tmpl_path).is_some()
566+
}
567+
568+
pub(crate) fn wxml_converted_expr_code(&mut self, abs_path: &Path, ts_env: &str) -> anyhow::Result<String> {
569+
let tmpl_path = self.unix_rel_path_or_fallback(&abs_path);
570+
let expr = self.template_group.get_tmpl_converted_expr(&tmpl_path, ts_env)?;
571+
let code = expr.code().to_string();
572+
self.cached_wxml_converted_expr.insert(tmpl_path, expr);
573+
Ok(code)
574+
}
575+
576+
pub(crate) fn wxml_converted_expr_get_source_location(&self, abs_path: &Path, loc: Location) -> Option<Location> {
577+
let tmpl_path = self.unix_rel_path_or_fallback(&abs_path);
578+
self.cached_wxml_converted_expr
579+
.get(&tmpl_path)
580+
.and_then(|x| x.get_source_location(loc))
581+
}
582+
583+
pub(crate) fn wxml_converted_expr_get_token_at_source_position(
584+
&self,
585+
abs_path: &Path,
586+
pos: crate::wxss::Position,
587+
) -> Option<(Location, crate::wxss::Position)> {
588+
let tmpl_path = self.unix_rel_path_or_fallback(&abs_path);
589+
self.cached_wxml_converted_expr
590+
.get(&tmpl_path)
591+
.and_then(|x| x.get_token_at_source_position(pos))
592+
}
593+
560594
pub(crate) fn for_each_json_config(&self, mut f: impl FnMut(&Path, &JsonConfig)) {
561595
for (p, json_config) in self.json_config_map.iter() {
562596
f(p, json_config);

src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mod reference;
1515
mod semantic;
1616
mod symbol;
1717
mod utils;
18+
mod wxml_ts;
1819
mod wxml_utils;
1920
mod wxs;
2021
mod wxss;
@@ -100,6 +101,7 @@ async fn handle_request(
100101
($name:expr, $f:path) => {
101102
if method.as_str() == $name {
102103
let params = serde_json::from_value(params).map_err(|err| {
104+
log::error!("Invalid params: {:?}", err);
103105
anyhow::Error::from(err).context(format!("Invalid params on {:?}", method))
104106
})?;
105107
let ret = $f(ctx, params).await?;
@@ -115,6 +117,10 @@ async fn handle_request(
115117

116118
// handlers for each method
117119
handler!("shutdown", cleanup);
120+
handler!("glassEaselAnalyzer/tmplConvertedExprRelease", wxml_ts::tmpl_converted_expr_release);
121+
handler!("glassEaselAnalyzer/tmplConvertedExprCode", wxml_ts::tmpl_converted_expr_code);
122+
handler!("glassEaselAnalyzer/tmplConvertedExprGetSourceLocation", wxml_ts::tmpl_converted_expr_get_source_location);
123+
handler!("glassEaselAnalyzer/tmplConvertedExprGetTokenAtSourcePosition", wxml_ts::tmpl_converted_expr_get_token_at_source_position);
118124
handler!("textDocument/foldingRange", folding::folding_range);
119125
handler!("textDocument/semanticTokens/full", semantic::tokens_full);
120126
handler!("textDocument/semanticTokens/range", semantic::tokens_range);

src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub(crate) fn location_to_lsp_range(loc: &Location) -> lsp_types::Range {
9797
}
9898
}
9999

100-
pub(crate) fn _lsp_range_to_location(loc: &lsp_types::Range) -> Location {
100+
pub(crate) fn lsp_range_to_location(loc: &lsp_types::Range) -> Location {
101101
let start = Position {
102102
line: loc.start.line,
103103
utf16_col: loc.start.character,

src/wxml_ts.rs

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
use lsp_types::{Position, Range, Url};
2+
use serde::{Deserialize, Serialize};
3+
4+
use crate::{
5+
context::FileLang, utils::{location_to_lsp_range, lsp_range_to_location}, ServerContext
6+
};
7+
8+
#[derive(Debug, Clone, Deserialize)]
9+
#[serde(rename_all = "camelCase")]
10+
pub(crate) struct TmplConvertedExprReleaseParams {
11+
text_document_uri: Url,
12+
}
13+
14+
pub(crate) async fn tmpl_converted_expr_release(
15+
ctx: ServerContext,
16+
params: TmplConvertedExprReleaseParams,
17+
) -> anyhow::Result<bool> {
18+
let ret = ctx
19+
.clone()
20+
.project_thread_task(
21+
&params.text_document_uri,
22+
move |project, abs_path, file_lang| -> anyhow::Result<bool> {
23+
let success = if let Some(_) = project.cached_file_content(&abs_path) {
24+
match file_lang {
25+
FileLang::Wxml => {
26+
project.wxml_converted_expr_release(&abs_path)
27+
}
28+
_ => false,
29+
}
30+
} else {
31+
false
32+
};
33+
Ok(success)
34+
},
35+
)
36+
.await??;
37+
Ok(ret)
38+
}
39+
40+
#[derive(Debug, Clone, Deserialize)]
41+
#[serde(rename_all = "camelCase")]
42+
pub(crate) struct TmplConvertedExprCodeParams {
43+
text_document_uri: Url,
44+
ts_env: String,
45+
}
46+
47+
#[derive(Debug, Clone, Serialize)]
48+
#[serde(rename_all = "camelCase")]
49+
pub(crate) struct TmplConvertedExprCode {
50+
code: String,
51+
}
52+
53+
pub(crate) async fn tmpl_converted_expr_code(
54+
ctx: ServerContext,
55+
params: TmplConvertedExprCodeParams,
56+
) -> anyhow::Result<Option<TmplConvertedExprCode>> {
57+
let ret = ctx
58+
.clone()
59+
.project_thread_task(
60+
&params.text_document_uri,
61+
move |project, abs_path, file_lang| -> anyhow::Result<Option<TmplConvertedExprCode>> {
62+
let code = if let Some(_) = project.cached_file_content(&abs_path) {
63+
match file_lang {
64+
FileLang::Wxml => {
65+
let code = project.wxml_converted_expr_code(&abs_path, &params.ts_env)?;
66+
Some(TmplConvertedExprCode { code })
67+
}
68+
_ => None,
69+
}
70+
} else {
71+
None
72+
};
73+
Ok(code)
74+
},
75+
)
76+
.await??;
77+
Ok(ret)
78+
}
79+
80+
#[derive(Debug, Clone, Deserialize)]
81+
#[serde(rename_all = "camelCase")]
82+
pub(crate) struct TmplConvertedExprGetSourceLocationParams {
83+
text_document_uri: Url,
84+
loc: Range,
85+
}
86+
87+
#[derive(Debug, Clone, Serialize)]
88+
#[serde(rename_all = "camelCase")]
89+
pub(crate) struct TmplConvertedExprGetSourceLocation {
90+
src: Range,
91+
}
92+
93+
pub(crate) async fn tmpl_converted_expr_get_source_location(
94+
ctx: ServerContext,
95+
params: TmplConvertedExprGetSourceLocationParams,
96+
) -> anyhow::Result<Option<TmplConvertedExprGetSourceLocation>> {
97+
let ret = ctx
98+
.clone()
99+
.project_thread_task(
100+
&params.text_document_uri,
101+
move |project, abs_path, file_lang| -> anyhow::Result<Option<TmplConvertedExprGetSourceLocation>> {
102+
let src_loc = if let Some(_) = project.cached_file_content(&abs_path) {
103+
match file_lang {
104+
FileLang::Wxml => {
105+
let loc = lsp_range_to_location(&params.loc);
106+
project.wxml_converted_expr_get_source_location(&abs_path, loc)
107+
}
108+
_ => None,
109+
}
110+
} else {
111+
None
112+
};
113+
let src = src_loc.as_ref().map(|x| location_to_lsp_range(x));
114+
Ok(src.map(|src| TmplConvertedExprGetSourceLocation { src }))
115+
},
116+
)
117+
.await??;
118+
Ok(ret)
119+
}
120+
121+
#[derive(Debug, Clone, Deserialize)]
122+
#[serde(rename_all = "camelCase")]
123+
pub(crate) struct TmplConvertedExprGetTokenAtSourcePositionParams {
124+
text_document_uri: Url,
125+
pos: Position,
126+
}
127+
128+
#[derive(Debug, Clone, Serialize)]
129+
#[serde(rename_all = "camelCase")]
130+
pub(crate) struct TmplConvertedExprGetTokenAtSourcePosition {
131+
src: Range,
132+
dest: Position
133+
}
134+
135+
pub(crate) async fn tmpl_converted_expr_get_token_at_source_position(
136+
ctx: ServerContext,
137+
params: TmplConvertedExprGetTokenAtSourcePositionParams,
138+
) -> anyhow::Result<Option<TmplConvertedExprGetTokenAtSourcePosition>> {
139+
let ret = ctx
140+
.clone()
141+
.project_thread_task(
142+
&params.text_document_uri,
143+
move |project, abs_path, file_lang| -> anyhow::Result<Option<TmplConvertedExprGetTokenAtSourcePosition>> {
144+
let ret = if let Some(_) = project.cached_file_content(&abs_path) {
145+
match file_lang {
146+
FileLang::Wxml => {
147+
let pos = crate::wxss::Position { line: params.pos.line, utf16_col: params.pos.character };
148+
project.wxml_converted_expr_get_token_at_source_position(&abs_path, pos)
149+
}
150+
_ => None,
151+
}
152+
} else {
153+
None
154+
};
155+
let ret = ret.map(|(src, dest)| {
156+
TmplConvertedExprGetTokenAtSourcePosition {
157+
src: location_to_lsp_range(&src),
158+
dest: Position { line: dest.line, character: dest.utf16_col },
159+
}
160+
});
161+
Ok(ret)
162+
},
163+
)
164+
.await??;
165+
Ok(ret)
166+
}

0 commit comments

Comments
 (0)