@@ -130,133 +130,6 @@ function postprocess_js(result: ITranspilationResult) {
130130 // but they do no harm and should go unnoticed
131131 result . js = result . js . replaceAll ( / 𒐛 : 𒐛 , ? / g, '' )
132132
133- // console.time('var-decl-fix')
134- //////////////////////////////////////
135- ///////// Modify variable declarations to solve various TS compiler errors:
136- // Should not be error but is:
137- // xy = 123 # Error: Variable 'xy' implicitly has type 'any' in some locations where its type cannot be determined.CoffeeSense [TS](7034)
138- // => xy # Error: Variable 'xy' implicitly has an 'any' type.CoffeeSense [TS](7005)
139- //////// and
140- // Should be error but is not:
141- // a = 1
142- // a = 'one'
143- /////// This is because the cs compiler puts variable declarations to the front:
144- // Translates to:
145- // var a;
146- // a = 1;
147- // a = 'one';
148- /////// and now `a` is of type `number | string` (https://github.com/microsoft/TypeScript/issues/45369).
149- // Below is a hacky workaround that should fix these issues in most cases. It moves the
150- // declaration part (`var`) down to the variable's first implementation position.
151- // This works only with easy implementations and single-variable array destructuring:
152- /*
153- var a, b, c;
154- a = 1;
155- [b] = 2;
156- ({c} = 3);
157- */
158- // Shall become:
159- /*
160- var c;
161- let a = 1; // added let
162- let [b] = 2; // added let
163- ({c} = 3); // unchanged because of surrounding braces
164- */
165- // similarly, array destructors with more than one variable cannot be changed.
166- // Returns stay untouched (return x = 1) too.
167- const js_lines = result . js . split ( '\n' )
168- const js_line_nos = Array . from ( Array ( js_lines . length ) . keys ( ) )
169- // Part 1: Determine declaration areas (` var x, y;`)
170- const js_decl_lines_info = js_line_nos
171- . map ( decl_line_no => {
172- const match = js_lines [ decl_line_no ] ! . match ( / ^ ( \s * ) ( v a r ) ( .+ ) ; $ / )
173- if ( match ) {
174- const var_decl_infos = match [ 3 ] ! . split ( ', ' ) . map ( var_name => ( {
175- var_name,
176- decl_indent : match [ 1 ] ! . length ,
177- decl_line_no,
178- } ) )
179- return {
180- decl_line_no,
181- var_decl_infos,
182- }
183- }
184- return null
185- } )
186- . filter ( Boolean )
187- // Part 2: For each `var` decl, find fitting first impl statement
188- // (`x = 1`), if present, and return new line content (`let x = 1`).
189- // Might as well be `var x = 1` but this helps differentiating/debugging
190- const js_impl_line_changes = js_decl_lines_info
191- . map ( info => info ! . var_decl_infos )
192- . flat ( )
193- . map ( ( { var_name, decl_indent, decl_line_no } ) => {
194- const js_line_nos_after_decl = js_line_nos . slice ( decl_line_no )
195- for ( const impl_line_no of js_line_nos_after_decl ) {
196- const line = js_lines [ impl_line_no ] !
197- const impl_whitespace = line . match ( / ^ \s * / ) ! [ 0 ] !
198- const impl_indent = impl_whitespace . length
199- if ( impl_indent < decl_indent )
200- // Parent block scope. Need to skip this variable then, no impl has been found
201- // before current block got closed. It is important to stop here, as otherwise
202- // it might later match an impl from *another* decl of the same var name
203- return null
204- const var_impl_text = `${ var_name } = `
205- if ( line . substr ( impl_indent , var_impl_text . length ) === var_impl_text ) {
206- if ( impl_indent > decl_indent )
207- // This is a conditional first value assignment and type can not safely be set
208- return null
209- const rest_of_line = line . slice ( impl_indent + var_impl_text . length )
210- return {
211- var_name,
212- impl_line_no,
213- decl_line_no,
214- new_line_content : `${ impl_whitespace } let ${ var_impl_text } ${ rest_of_line } ` ,
215- new_let_column : impl_indent ,
216- }
217- }
218- }
219- return null
220- } ) . filter ( Boolean )
221- // Part 3: Apply Part 2 changes and update source maps of those lines
222- for ( const change of js_impl_line_changes ) {
223- js_lines [ change ! . impl_line_no ] = change ! . new_line_content
224- const map_columns = result . source_map [ change ! . impl_line_no ] ! . columns
225- const map_current_impl_start = map_columns [ change ! . new_let_column ] !
226- // Can be null in cases where the variable is not user-set but e.g. a helper
227- // variable put there by the cs compiler itself and ignored otherwise
228- if ( map_current_impl_start != null ) {
229- map_columns . splice (
230- change ! . new_let_column ,
231- 0 ,
232- ..."let " . split ( '' ) . map ( ( _ , i ) => ( {
233- ...map_current_impl_start ,
234- column : map_current_impl_start . column + i
235- } ) ) )
236- for ( let i = map_current_impl_start . column + "let " . length ; i < map_columns . length + "let " . length ; i ++ ) {
237- if ( map_columns [ i ] )
238- map_columns [ i ] ! . column += "let " . length // or = i
239- }
240- }
241- }
242- // Part 4: Update decl lines (Part 1). Where no impl lines were found (Part 2),
243- // keep them. If all were modified, an empty line will be put.
244- for ( const decl_line_info of js_decl_lines_info ) {
245- let new_decl_line = decl_line_info ! . var_decl_infos
246- . filter ( decl_info => ! js_impl_line_changes . some ( impl_change =>
247- impl_change ! . var_name === decl_info . var_name &&
248- impl_change ! . decl_line_no === decl_info . decl_line_no ) )
249- . map ( i => i . var_name )
250- . join ( ', ' )
251- if ( new_decl_line )
252- // Those that could not be changed
253- new_decl_line = 'var ' + new_decl_line
254- js_lines [ decl_line_info ! . decl_line_no ] = new_decl_line
255- }
256-
257- result . js = js_lines . join ( '\n' )
258- // console.timeEnd('var-decl-fix')
259-
260133 /* Prefer object method shorthand */
261134 result . js = result . js . replaceAll ( / ( [ a - z A - Z 0 - 9 _ $ ] + ) : ( a s y n c ) ? f u n c t i o n ( \* ? ) \( / g, ( _ , func_name , asynk , asterisk ) =>
262135 `${ asynk || '' } ${ asterisk } ${ func_name } (`
0 commit comments