Repository: sveltejs/language-tools
Pull request #1147 (2021-08-25 12:38:55)

(fix) don't prepend semi in unsafe places
no semi when expression is the first inside an if/for/while block
#1146


Patch:
diff --git a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts
index 12bf3168..fc698843 100644
--- a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts
+++ b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts
@@ -3,7 +3,7 @@ import { Node } from 'estree-walker';
 import * as ts from 'typescript';
 import {
     getBinaryAssignmentExpr,
-    isFirstInAnExpressionStatement,
+    isSafeToPrefixWithSemicolon,
     isNotPropertyNameOfImport
 } from './utils/tsAst';
 import { ExportedNames, is$$PropsDeclaration } from './nodes/ExportedNames';
@@ -164,7 +164,7 @@ export function processInstanceScriptContent(
         // - in order to get ts errors if store is not assignable to SvelteStore
         // - use $store variable defined above to get ts flow control
         const dollar = str.original.indexOf('$', ident.getStart() + astOffset);
-        const getPrefix = isFirstInAnExpressionStatement(ident) ? ';' : '';
+        const getPrefix = isSafeToPrefixWithSemicolon(ident) ? ';' : '';
         str.overwrite(dollar, dollar + 1, getPrefix + '(__sveltets_1_store_get(');
         str.prependLeft(ident.end + astOffset, `), $${storename})`);
     };
diff --git a/packages/svelte2tsx/src/svelte2tsx/utils/tsAst.ts b/packages/svelte2tsx/src/svelte2tsx/utils/tsAst.ts
index 935fdecc..5bc60743 100644
--- a/packages/svelte2tsx/src/svelte2tsx/utils/tsAst.ts
+++ b/packages/svelte2tsx/src/svelte2tsx/utils/tsAst.ts
@@ -181,7 +181,7 @@ export function getNamesFromLabeledStatement(node: ts.LabeledStatement): string[
     );
 }
 
-export function isFirstInAnExpressionStatement(node: ts.Identifier): boolean {
+export function isSafeToPrefixWithSemicolon(node: ts.Identifier): boolean {
     let parent = node.parent;
     while (parent && !ts.isExpressionStatement(parent)) {
         parent = parent.parent;
@@ -189,5 +189,15 @@ export function isFirstInAnExpressionStatement(node: ts.Identifier): boolean {
     if (!parent) {
         return false;
     }
-    return parent.getStart() === node.getStart();
+    return (
+        parent.getStart() === node.getStart() &&
+        !(
+            parent.parent &&
+            (ts.isIfStatement(parent.parent) ||
+                ts.isForStatement(parent.parent) ||
+                ts.isForInStatement(parent.parent) ||
+                ts.isForOfStatement(parent.parent) ||
+                ts.isWhileStatement(parent.parent))
+        )
+    );
 }


Test patch:
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/$store-inside-block-without-braces/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/$store-inside-block-without-braces/expected.tsx
new file mode 100644
index 00000000..10d43297
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/$store-inside-block-without-braces/expected.tsx
@@ -0,0 +1,33 @@
+///<reference types="svelte" />
+<></>;function render() {
+
+    const store1 = ''/*Ωignore_startΩ*/;let $store1 = __sveltets_1_store_get(store1);/*Ωignore_endΩ*/;
+
+    if (store1)
+        (__sveltets_1_store_get(store1), $store1)
+    else if (store1)
+        (__sveltets_1_store_get(store1), $store1)
+    else
+        (__sveltets_1_store_get(store), $store)
+    if (store1)
+        store1.set( 1)
+    if (store1)
+        (__sveltets_1_store_get(store1), $store1).x = 1
+
+    for (let i=0; i < 1; i++)
+        (__sveltets_1_store_get(store1), $store1)
+
+    for (const a of b)
+        (__sveltets_1_store_get(store1), $store1)
+
+    for (const a in b)
+        (__sveltets_1_store_get(store1), $store1)
+
+    while (true)
+        (__sveltets_1_store_get(store1), $store1)
+;
+() => (<></>);
+return { props: {}, slots: {}, getters: {}, events: {} }}
+
+export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(__sveltets_1_with_any_event(render()))) {
+}
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/$store-inside-block-without-braces/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/$store-inside-block-without-braces/input.svelte
new file mode 100644
index 00000000..bd6e022d
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/$store-inside-block-without-braces/input.svelte
@@ -0,0 +1,26 @@
+<script>
+    const store1 = '';
+
+    if (store1)
+        $store1
+    else if (store1)
+        $store1
+    else
+        $store
+    if (store1)
+        $store1 = 1
+    if (store1)
+        $store1.x = 1
+
+    for (let i=0; i < 1; i++)
+        $store1
+
+    for (const a of b)
+        $store1
+
+    for (const a in b)
+        $store1
+
+    while (true)
+        $store1
+</script>