Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: copy global types into hidden folder in IDE contexts #2561

Merged
merged 2 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/language-server/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dist/
.vscode/
node_modules/
!test/plugins/typescript/features/diagnostics/fixtures/exports-map-svelte/node_modules/
!test/plugins/typescript/features/diagnostics/fixtures/exports-map-svelte/node_modules/package
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export class LSAndTSDocResolver {
}

this.lsDocumentContext = {
isSvelteCheck: !!this.options?.isSvelteCheck,
ambientTypesSource: this.options?.isSvelteCheck ? 'svelte-check' : 'svelte2tsx',
createDocument: this.createDocument,
transformOnTemplateError: !this.options?.isSvelteCheck,
Expand Down
28 changes: 9 additions & 19 deletions packages/language-server/src/plugins/typescript/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
isSvelteFilePath
} from './utils';
import { createProject, ProjectService } from './serviceCache';
import { internalHelpers } from 'svelte2tsx';

export interface LanguageServiceContainer {
readonly tsconfigPath: string;
Expand Down Expand Up @@ -132,6 +133,7 @@ export function __resetCache() {
}

export interface LanguageServiceDocumentContext {
isSvelteCheck: boolean;
ambientTypesSource: string;
transformOnTemplateError: boolean;
createDocument: (fileName: string, content: string) => Document;
Expand Down Expand Up @@ -1211,25 +1213,13 @@ async function createLanguageService(
}

function getSvelteShimFiles() {
const isSvelte3 = sveltePackageInfo.version.major === 3;
const svelteHtmlDeclaration = isSvelte3
? undefined
: join(sveltePackageInfo.path, 'svelte-html.d.ts');
const svelteHtmlFallbackIfNotExist =
svelteHtmlDeclaration && tsSystem.fileExists(svelteHtmlDeclaration)
? svelteHtmlDeclaration
: './svelte-jsx-v4.d.ts';

const svelteTsxFiles = (
isSvelte3
? ['./svelte-shims.d.ts', './svelte-jsx.d.ts', './svelte-native-jsx.d.ts']
: [
'./svelte-shims-v4.d.ts',
svelteHtmlFallbackIfNotExist,
'./svelte-native-jsx.d.ts'
]
).map((f) => tsSystem.resolvePath(resolve(svelteTsPath, f)));

const svelteTsxFiles = internalHelpers.get_global_types(
tsSystem,
sveltePackageInfo.version.major === 3,
sveltePackageInfo.path,
svelteTsPath,
docContext.isSvelteCheck ? undefined : tsconfigPath || workspacePath
);
const result = new FileSet(tsSystem.useCaseSensitiveFileNames);

svelteTsxFiles.forEach((f) => result.add(normalizePath(f)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('service', () => {

const rootUris = [pathToUrl(testDir)];
const lsDocumentContext: LanguageServiceDocumentContext = {
isSvelteCheck: false,
ambientTypesSource: 'svelte2tsx',
createDocument(fileName, content) {
return new Document(pathToUrl(fileName), content);
Expand Down
7 changes: 7 additions & 0 deletions packages/svelte2tsx/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ export function emitDts(config: EmitDtsConfig): Promise<void>;
* static top level `ts` namespace, it must be passed as a parameter.
*/
export const internalHelpers: {
get_global_types: (
tsSystem: ts.System,
isSvelte3: boolean,
sveltePath: string,
typesPath: string,
hiddenFolderPath?: string,
) => string[],
isKitFile: (
fileName: string,
options: InternalHelpers.KitFilesSettings
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte2tsx/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svelte2tsx",
"version": "0.7.0",
"version": "0.7.23",
"description": "Convert Svelte components to TSX for type checking",
"author": "David Pershouse",
"license": "MIT",
Expand Down
72 changes: 72 additions & 0 deletions packages/svelte2tsx/src/helpers/files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { basename, dirname, join, resolve } from 'path';
import type ts from 'typescript';

/**
* Returns the path to the global svelte2tsx files that should be included in the project.
* Creates a hidden folder in the user's node_modules if `hiddenFolderPath` is provided.
*/
export function get_global_types(
tsSystem: ts.System,
isSvelte3: boolean,
sveltePath: string,
typesPath: string,
hiddenFolderPath?: string
): string[] {
const svelteHtmlPath = isSvelte3 ? undefined : join(sveltePath, 'svelte-html.d.ts');
const svelteHtmlPathExists = svelteHtmlPath && tsSystem.fileExists(svelteHtmlPath);
const svelteHtmlFile = svelteHtmlPathExists ? svelteHtmlPath : './svelte-jsx-v4.d.ts';

let svelteTsxFiles: string[];
if (isSvelte3) {
svelteTsxFiles = ['./svelte-shims.d.ts', './svelte-jsx.d.ts', './svelte-native-jsx.d.ts'];
} else {
svelteTsxFiles = ['./svelte-shims-v4.d.ts', './svelte-native-jsx.d.ts'];
if (!svelteHtmlPathExists) {
svelteTsxFiles.push(svelteHtmlPath);
}
}
svelteTsxFiles = svelteTsxFiles.map((f) => tsSystem.resolvePath(resolve(typesPath, f)));

if (hiddenFolderPath) {
try {
// IDE context - the `import('svelte')` statements inside the d.ts files will load the Svelte version of
// the extension, which can cause all sorts of problems. Therefore put the files into a hidden folder in
// the user's node_modules, preferably next to the Svelte package.
let path = dirname(sveltePath);

if (!tsSystem.directoryExists(resolve(path, 'node_modules'))) {
path = hiddenFolderPath;

while (path && !tsSystem.directoryExists(resolve(path, 'node_modules'))) {
const parent = dirname(path);
if (path === parent) {
path = '';
break;
}
path = parent;
}
}

if (path) {
const hiddenPath = resolve(path, 'node_modules/.svelte2tsx-language-server-files');
const newFiles = [];
for (const f of svelteTsxFiles) {
const hiddenFile = resolve(hiddenPath, basename(f));
const existing = tsSystem.readFile(hiddenFile);
const toWrite = tsSystem.readFile(f) || '';
if (existing !== toWrite) {
tsSystem.writeFile(hiddenFile, toWrite);
}
newFiles.push(hiddenFile);
}
svelteTsxFiles = newFiles;
}
} catch (e) {}
}

if (svelteHtmlPathExists) {
svelteTsxFiles.push(tsSystem.resolvePath(resolve(typesPath, svelteHtmlFile)));
}

return svelteTsxFiles;
}
4 changes: 3 additions & 1 deletion packages/svelte2tsx/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { get_global_types } from './files';
import {
isHooksFile,
isKitFile,
Expand All @@ -23,5 +24,6 @@ export const internalHelpers = {
upsertKitFile,
toVirtualPos,
toOriginalPos,
findExports
findExports,
get_global_types
};
42 changes: 19 additions & 23 deletions packages/typescript-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
importSvelteCompiler,
isSvelteProject
} from './utils';
import { internalHelpers } from 'svelte2tsx';

function init(modules: { typescript: typeof ts }): ts.server.PluginModule {
const configManager = new ConfigManager();
Expand Down Expand Up @@ -200,32 +201,27 @@ function init(modules: { typescript: typeof ts }): ts.server.PluginModule {
}

const svelteTsPath = dirname(require.resolve('svelte2tsx'));
const sveltePath = require.resolve(
const svelteCompilerPath = require.resolve(
'svelte/compiler',
configFilePath ? { paths: [configFilePath] } : undefined
);
const VERSION = require(sveltePath).VERSION;
const isSvelte3 = VERSION.split('.')[0] === '3';
const svelteHtmlDeclaration = isSvelte3
? undefined
: join(dirname(sveltePath), 'svelte-html.d.ts');
const svelteHtmlFallbackIfNotExist =
svelteHtmlDeclaration && modules.typescript.sys.fileExists(svelteHtmlDeclaration)
? svelteHtmlDeclaration
: './svelte-jsx-v4.d.ts';
const svelteTsxFiles = (
isSvelte3
? ['./svelte-shims.d.ts', './svelte-jsx.d.ts', './svelte-native-jsx.d.ts']
: [
'./svelte-shims-v4.d.ts',
svelteHtmlFallbackIfNotExist,
'./svelte-native-jsx.d.ts'
]
).map((f) => modules.typescript.sys.resolvePath(resolve(svelteTsPath, f)));

resolvedSvelteTsxFiles = svelteTsxFiles;

return svelteTsxFiles;
const sveltePath = dirname(
require.resolve(
'svelte/package.json',
configFilePath ? { paths: [configFilePath] } : undefined
)
);
const VERSION = require(svelteCompilerPath).VERSION;

resolvedSvelteTsxFiles = internalHelpers.get_global_types(
modules.typescript.sys,
VERSION.split('.')[0] === '3',
sveltePath,
svelteTsPath,
configFilePath
);

return resolvedSvelteTsxFiles;
}

function isSvelteProjectWithCache(project: ts.server.Project) {
Expand Down