Repository: sveltejs/language-tools
Pull request #1129 (2021-08-02 05:23:15)

(fix) svelte2tsx accessors config
#1127 

Add a new accessors config for svelte2tsx and pass the config from the language server. Notice this PR doesn't add the config to the `emitDts` function. Because the `compilerOption` is currently not being passed in. I'll leave this for later. 


Patch:
diff --git a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts
index 2b1e2201..7b74b553 100644
--- a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts
+++ b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts
@@ -166,7 +166,10 @@ function preprocessSvelteFile(document: Document, options: SvelteSnapshotOptions
             filename: document.getFilePath() ?? undefined,
             isTsFile: scriptKind === ts.ScriptKind.TSX,
             emitOnTemplateError: options.transformOnTemplateError,
-            namespace: document.config?.compilerOptions?.namespace
+            namespace: document.config?.compilerOptions?.namespace,
+            accessors:
+                document.config?.compilerOptions?.accessors ??
+                document.config?.compilerOptions?.customElement
         });
         text = tsx.code;
         tsxMap = tsx.map;
diff --git a/packages/svelte2tsx/index.d.ts b/packages/svelte2tsx/index.d.ts
index 74b6d4fa..b012d1ab 100644
--- a/packages/svelte2tsx/index.d.ts
+++ b/packages/svelte2tsx/index.d.ts
@@ -34,6 +34,7 @@ export function svelte2tsx(
         emitOnTemplateError?: boolean;
         /**
          * The namespace option from svelte config
+         * see https://svelte.dev/docs#svelte_compile for more info
          */
         namespace?: string;
         /**
@@ -44,7 +45,13 @@ export function svelte2tsx(
          * The shims need to be provided by the user ambient-style,
          * for example through `filenames.push(require.resolve('svelte2tsx/svelte-shims.d.ts'))`.
          */
-        mode?: 'tsx' | 'dts'
+        mode?: 'tsx' | 'dts',
+        /**
+         * The accessor option from svelte config. 
+         * Would be overridden by the same config in the svelte:option element if exist
+         * see https://svelte.dev/docs#svelte_compile for more info
+         */
+        accessors?: boolean
     }
 ): SvelteCompiledToTsx
 
diff --git a/packages/svelte2tsx/src/svelte2tsx/index.ts b/packages/svelte2tsx/src/svelte2tsx/index.ts
index fea34351..19b53cba 100644
--- a/packages/svelte2tsx/src/svelte2tsx/index.ts
+++ b/packages/svelte2tsx/src/svelte2tsx/index.ts
@@ -38,14 +38,14 @@ type TemplateProcessResult = {
 
 function processSvelteTemplate(
     str: MagicString,
-    options?: { emitOnTemplateError?: boolean; namespace?: string }
+    options?: { emitOnTemplateError?: boolean; namespace?: string; accessors?: boolean }
 ): TemplateProcessResult {
     const { htmlxAst, tags } = parseHtmlx(str.original, options);
 
     let uses$$props = false;
     let uses$$restProps = false;
     let uses$$slots = false;
-    let usesAccessors = false;
+    let usesAccessors = !!options.accessors;
 
     const componentDocumentation = new ComponentDocumentation();
 
@@ -288,6 +288,7 @@ export function svelte2tsx(
         emitOnTemplateError?: boolean;
         namespace?: string;
         mode?: 'tsx' | 'dts';
+        accessors?: boolean;
     } = {}
 ) {
     const str = new MagicString(svelte);


Test patch:
diff --git a/packages/language-server/test/plugins/typescript/features/DiagnosticsProvider.test.ts b/packages/language-server/test/plugins/typescript/features/DiagnosticsProvider.test.ts
index 24c9d2f8..3f265503 100644
--- a/packages/language-server/test/plugins/typescript/features/DiagnosticsProvider.test.ts
+++ b/packages/language-server/test/plugins/typescript/features/DiagnosticsProvider.test.ts
@@ -1777,4 +1777,64 @@ describe('DiagnosticsProvider', () => {
         const diagnostics = await plugin.getDiagnostics(document);
         assert.deepStrictEqual(diagnostics, []);
     });
+
+    it('checks component with accessors when configured in svelte.config.js', async () => {
+        const { plugin, document } = setup('with-svelte-config/accessors-consumer.svelte');
+
+        const diagnostics = await plugin.getDiagnostics(document);
+        assert.deepStrictEqual(diagnostics, <typeof diagnostics>[
+            {
+                code: 2322,
+                message: "Type '\"\"' is not assignable to type 'number | undefined'.",
+                range: {
+                    end: {
+                        character: 12,
+                        line: 9
+                    },
+                    start: {
+                        character: 7,
+                        line: 9
+                    }
+                },
+                severity: 1,
+                source: 'ts',
+                tags: []
+            },
+            {
+                code: 2322,
+                message: "Type '\"\"' is not assignable to type 'number | undefined'.",
+                range: {
+                    end: {
+                        character: 20,
+                        line: 9
+                    },
+                    start: {
+                        character: 15,
+                        line: 9
+                    }
+                },
+                severity: 1,
+                source: 'ts',
+                tags: []
+            },
+            {
+                code: 2339,
+                message:
+                    "Property 'abc' does not exist on type 'AccessorsAndOption__SvelteComponent_'.",
+                range: {
+                    end: {
+                        character: 29,
+                        line: 9
+                    },
+                    start: {
+                        character: 26,
+                        line: 9
+                    }
+                },
+                severity: 1,
+                source: 'ts',
+                tags: []
+            }
+        ]);
+    });
 });
diff --git a/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/accessors-and-option.svelte b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/accessors-and-option.svelte
new file mode 100644
index 00000000..79fda213
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/accessors-and-option.svelte
@@ -0,0 +1,4 @@
+<script lang="ts">
+    export let abc = 1;
+</script>
+<svelte:options accessors={false} />
\ No newline at end of file
diff --git a/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/accessors.svelte b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/accessors.svelte
new file mode 100644
index 00000000..9dc89036
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/accessors.svelte
@@ -0,0 +1,3 @@
+<script lang="ts">
+    export let abc = 1;
+</script>
\ No newline at end of file
diff --git a/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/svelte.config.js b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/svelte.config.js
new file mode 100644
index 00000000..df2b5891
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/acceesors/svelte.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+    /**
+     * @type {import('svelte/types/compiler/interfaces').CompileOptions}
+     */
+    compilerOptions: {
+        accessors: true
+    }
+};
diff --git a/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/accessors-consumer.svelte b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/accessors-consumer.svelte
new file mode 100644
index 00000000..8c732f55
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/accessors-consumer.svelte
@@ -0,0 +1,15 @@
+<script lang="ts">
+    import AccessorsAndOption from './acceesors/accessors-and-option.svelte';
+    import Accessors from './acceesors/accessors.svelte';
+    import CustomElement from './customElement/customElement.svelte';
+
+    let c: CustomElement;
+    let a: Accessors;
+    let ao: AccessorsAndOption;
+
+    $: c.abc = a.abc = ao.abc = '';
+</script>
+
+<CustomElement />
+<Accessors />
+<AccessorsAndOption />
\ No newline at end of file
diff --git a/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/customElement/customElement.svelte b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/customElement/customElement.svelte
new file mode 100644
index 00000000..9dc89036
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/customElement/customElement.svelte
@@ -0,0 +1,3 @@
+<script lang="ts">
+    export let abc = 1;
+</script>
\ No newline at end of file
diff --git a/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/customElement/svelte.config.js b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/customElement/svelte.config.js
new file mode 100644
index 00000000..b3f073e7
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/testfiles/diagnostics/with-svelte-config/customElement/svelte.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+    /**
+     * @type {import('svelte/types/compiler/interfaces').CompileOptions}
+     */
+    compilerOptions: {
+        customElement: true
+    }
+};
diff --git a/packages/svelte2tsx/test/helpers.ts b/packages/svelte2tsx/test/helpers.ts
index d80cbaba..f4eb8ddb 100644
--- a/packages/svelte2tsx/test/helpers.ts
+++ b/packages/svelte2tsx/test/helpers.ts
@@ -309,7 +309,8 @@ export function get_svelte2tsx_config(base: BaseConfig, sampleName: string): Sve
         emitOnTemplateError: base.emitOnTemplateError,
         isTsFile: sampleName.startsWith('ts-'),
         namespace: sampleName.endsWith('-foreign-ns') ? 'foreign' : null,
-        mode: sampleName.endsWith('-dts') ? 'dts' : undefined
+        mode: sampleName.endsWith('-dts') ? 'dts' : undefined,
+        accessors: sampleName.startsWith('accessors-config')
     };
 }
 
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config-attr-false/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config-attr-false/expected.tsx
new file mode 100644
index 00000000..ebc105de
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config-attr-false/expected.tsx
@@ -0,0 +1,11 @@
+///<reference types="svelte" />
+<></>;function render() {
+
+	 let foo: number = undefined;foo = __sveltets_1_any(foo);;
+;
+() => (<><svelteoptions accessors={false} />
+</>);
+return { props: {foo: foo}, slots: {}, getters: {}, events: {} }}
+
+export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(['foo'], __sveltets_1_with_any_event(render()))) {
+}
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config-attr-false/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config-attr-false/input.svelte
new file mode 100644
index 00000000..f864ab12
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config-attr-false/input.svelte
@@ -0,0 +1,4 @@
+<svelte:options accessors={false} />
+<script lang="ts">
+	export let foo: number = undefined;
+</script>
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config/expected.tsx
new file mode 100644
index 00000000..3a0e7d88
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config/expected.tsx
@@ -0,0 +1,13 @@
+///<reference types="svelte" />
+<></>;function render() {
+
+	 let foo: number = undefined;foo = __sveltets_1_any(foo);;
+;
+() => (<></>);
+return { props: {foo: foo}, slots: {}, getters: {}, events: {} }}
+
+export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(['foo'], __sveltets_1_with_any_event(render()))) {
+    get foo() { return render().props.foo }
+    /**accessor*/
+    set foo(_) {}
+}
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config/input.svelte
new file mode 100644
index 00000000..d84c092f
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/accessors-config/input.svelte
@@ -0,0 +1,3 @@
+<script lang="ts">
+	export let foo: number = undefined;
+</script>
\ No newline at end of file