Skip to content

Commit

Permalink
Toggle JSX namespace based on svelte vs svelte-native (#351)
Browse files Browse the repository at this point in the history
* Toggle JSX namespace based on svelte vs svelte-native

* add svelte-native-jsx.d.ts to the package

* lint fixes
  • Loading branch information
halfnelson committed Jul 25, 2020
1 parent 7f89480 commit d15939c
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export class RenameProviderImpl implements RenameProvider {
if (
!renameInfo.canRename ||
renameInfo.kind === ts.ScriptElementKind.jsxAttribute ||
renameInfo.fullDisplayName?.startsWith('JSX.')
renameInfo.fullDisplayName?.includes("JSX.IntrinsicElements")
) {
return null;
}
Expand Down
23 changes: 20 additions & 3 deletions packages/language-server/src/plugins/typescript/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function createLanguageService(
const svelteModuleLoader = createSvelteModuleLoader(getSnapshot, compilerOptions);

const svelteTsPath = dirname(require.resolve('svelte2tsx'));
const svelteTsxFiles = ['./svelte-shims.d.ts', './svelte-jsx.d.ts'].map((f) =>
const svelteTsxFiles = ['./svelte-shims.d.ts', './svelte-jsx.d.ts', './svelte-native-jsx.d.ts'].map((f) =>
ts.sys.resolvePath(resolve(svelteTsPath, f)),
);

Expand Down Expand Up @@ -162,8 +162,7 @@ export function createLanguageService(
declaration: false,
skipLibCheck: true,
// these are needed to handle the results of svelte2tsx preprocessing:
jsx: ts.JsxEmit.Preserve,
jsxFactory: 'h',
jsx: ts.JsxEmit.Preserve
};

// always let ts parse config to get default compilerOption
Expand Down Expand Up @@ -203,6 +202,24 @@ export function createLanguageService(
...forcedCompilerOptions,
};

// detect which JSX namespace to use (svelte | svelteNative) if not specified or not compatible
if (!compilerOptions.jsxFactory || !compilerOptions.jsxFactory.startsWith("svelte")) {
//default to regular svelte, this causes the usage of the "svelte.JSX" namespace
compilerOptions.jsxFactory = "svelte.createElement";

//override if we detect svelte-native
if (workspacePath) {
try {
const svelteNativePkgInfo = getPackageInfo('svelte-native', workspacePath);
if (svelteNativePkgInfo.path) {
compilerOptions.jsxFactory = "svelteNative.createElement";
}
} catch (e) {
//we stay regular svelte
}
}
}

return { compilerOptions, files };
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from 'vscode-languageserver';
import { CompletionsProviderImpl, CompletionEntryWithIdentifer } from '../../../../src/plugins/typescript/features/CompletionProvider';
import { LSAndTSDocResolver } from '../../../../src/plugins/typescript/LSAndTSDocResolver';
import { sortBy } from 'lodash';

const testDir = join(__dirname, '..');
const testFilesDir = join(testDir, 'testfiles');
Expand Down Expand Up @@ -182,8 +183,11 @@ describe('CompletionProviderImpl', () => {
];
const ignores = ['tsconfig.json', sourceFile];

const testfiles = readdirSync(testFilesDir)
.filter((f) => supportedExtensions.includes(extname(f)) && !ignores.includes(f));
const testfiles = readdirSync(testFilesDir, { withFileTypes: true })
.filter((f) => f.isDirectory()
|| (supportedExtensions.includes(extname(f.name))
&& !ignores.includes(f.name)))
.map(f => f.name);

const completions = await completionProvider.getCompletions(
document,
Expand All @@ -194,7 +198,10 @@ describe('CompletionProviderImpl', () => {
},
);

assert.deepStrictEqual(completions?.items.map(item => item.label), testfiles);
assert.deepStrictEqual(
sortBy(completions?.items.map(item => item.label), x => x),
sortBy(testfiles, x => x)
);
});

it('resolve auto import completion (is first import in file)', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,10 @@ describe('TypescriptPlugin', () => {

assert.deepStrictEqual(diagnostics, []);
});

it('handles svelte native syntax', async () => {
const { plugin, document } = setup('svelte-native/svelte-native.svelte');
const diagnostics = await plugin.getDiagnostics(document);
assert.deepStrictEqual(diagnostics, []);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<page>
<label class="info" horizontalAlignment="center" verticalAlignment="center" textWrap="true">
<formattedString>
<span class="fas" text="&#xf135;" />
<span text=" {message}" />
</formattedString>
</label>
</page>

<script lang="typescript">
let message: string = "Blank Svelte Native App"
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"compilerOptions": {
"jsxFactory": "svelteNative"
}
}
1 change: 1 addition & 0 deletions packages/svelte2tsx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"README.md",
"LICENSE",
"svelte-jsx.d.ts",
"svelte-native-jsx.d.ts",
"svelte-shims.d.ts"
],
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte2tsx/svelte-jsx.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/


declare namespace JSX {
declare namespace svelte.JSX {

/* svelte specific */
interface ElementClass {
Expand Down
20 changes: 20 additions & 0 deletions packages/svelte2tsx/svelte-native-jsx.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
declare namespace svelteNative.JSX {

/* svelte specific */
interface ElementClass {
$$prop_def: any;
}

interface ElementAttributesProperty {
$$prop_def: any; // specify the property name to use
}

// Add empty IntrinsicAttributes to prevent fallback to the one in the JSX namespace
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface IntrinsicAttributes {
}

interface IntrinsicElements {
[name: string]: { [name: string]: any };
}
}

0 comments on commit d15939c

Please sign in to comment.