diff --git a/src/main/java/dev/blachut/svelte/lang/codeInsight/SvelteTypeScriptImportsResolverProvider.kt b/src/main/java/dev/blachut/svelte/lang/codeInsight/SvelteTypeScriptImportsResolverProvider.kt new file mode 100644 index 00000000..45dc7306 --- /dev/null +++ b/src/main/java/dev/blachut/svelte/lang/codeInsight/SvelteTypeScriptImportsResolverProvider.kt @@ -0,0 +1,41 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package dev.blachut.svelte.lang.codeInsight + +import com.intellij.lang.typescript.modules.TypeScriptNodeReference +import com.intellij.lang.typescript.tsconfig.* +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiManager +import dev.blachut.svelte.lang.SvelteHtmlFileType +import dev.blachut.svelte.lang.isSvelteContext +import dev.blachut.svelte.lang.isTSLangValue +import dev.blachut.svelte.lang.psi.SvelteHtmlFile + +const val svelteExtension = ".svelte" +val svelteExtensionsWithDot = arrayOf(svelteExtension) + +class SvelteTypeScriptImportsResolverProvider : TypeScriptImportsResolverProvider { + override fun isDynamicFile(project: Project, file: VirtualFile): Boolean { + if (file.fileType != SvelteHtmlFileType.INSTANCE) return false + + val psiFile = PsiManager.getInstance(project).findFile(file) as? SvelteHtmlFile ?: return false + val langAttr = psiFile.instanceScript?.getAttribute("lang")?.value + return isTSLangValue(langAttr) + } + + override fun useExplicitExtension(extensionWithDot: String): Boolean = extensionWithDot == svelteExtension + override fun getExtensions(): Array = svelteExtensionsWithDot + + override fun contributeResolver(project: Project, config: TypeScriptConfig): TypeScriptFileImportsResolver? { + // TODO check if package.json includes svelte + return TypeScriptFileImportsResolverImpl(project, config.resolveContext, TypeScriptNodeReference.TS_PROCESSOR, svelteExtensionsWithDot, listOf(SvelteHtmlFileType.INSTANCE)) + } + + override fun contributeResolver(project: Project, + context: TypeScriptImportResolveContext, + contextFile: VirtualFile): TypeScriptFileImportsResolver? { + if (!isSvelteContext(contextFile)) return null + + return TypeScriptFileImportsResolverImpl(project, context, TypeScriptNodeReference.TS_PROCESSOR, svelteExtensionsWithDot, listOf(SvelteHtmlFileType.INSTANCE)) + } +} diff --git a/src/main/java/dev/blachut/svelte/lang/psi/SvelteJSElementTypes.kt b/src/main/java/dev/blachut/svelte/lang/psi/SvelteJSElementTypes.kt index 617d5231..46f4b979 100644 --- a/src/main/java/dev/blachut/svelte/lang/psi/SvelteJSElementTypes.kt +++ b/src/main/java/dev/blachut/svelte/lang/psi/SvelteJSElementTypes.kt @@ -5,6 +5,7 @@ import com.intellij.lang.javascript.JSCompositeElementType import com.intellij.lang.javascript.types.JSEmbeddedContentElementType import com.intellij.lang.javascript.types.JSExpressionElementType import com.intellij.lang.javascript.types.JSParameterElementType +import com.intellij.lang.javascript.types.TypeScriptEmbeddedContentElementType import com.intellij.psi.PsiElement import com.intellij.psi.tree.IElementType import dev.blachut.svelte.lang.SvelteJSLanguage @@ -34,7 +35,7 @@ object SvelteJSElementTypes { } } - val EMBEDDED_CONTENT_MODULE_TS = object : JSEmbeddedContentElementType(SvelteTypeScriptLanguage.INSTANCE, "MOD_SVELTE_TS_") { + val EMBEDDED_CONTENT_MODULE_TS = object : TypeScriptEmbeddedContentElementType(SvelteTypeScriptLanguage.INSTANCE, "MOD_SVELTE_TS_") { override fun isModule() = true override fun toModule() = this diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 5149309b..fee68715 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -102,5 +102,6 @@ + diff --git a/src/test/java/dev/blachut/svelte/lang/codeInsight/SvelteTypeScriptHighlightingTest.kt b/src/test/java/dev/blachut/svelte/lang/codeInsight/SvelteTypeScriptHighlightingTest.kt index a4d0e6dd..4fc15744 100644 --- a/src/test/java/dev/blachut/svelte/lang/codeInsight/SvelteTypeScriptHighlightingTest.kt +++ b/src/test/java/dev/blachut/svelte/lang/codeInsight/SvelteTypeScriptHighlightingTest.kt @@ -3,6 +3,9 @@ package dev.blachut.svelte.lang.codeInsight import com.intellij.testFramework.fixtures.BasePlatformTestCase class SvelteTypeScriptHighlightingTest : BasePlatformTestCase() { + override fun getTestDataPath(): String = "src/test/resources" + override fun getBasePath(): String = "dev/blachut/svelte/lang/codeInsight/tsHighlighting" + override fun setUp() { super.setUp() myFixture.enableInspections(*SvelteHighlightingTest.configureDefaultLocalInspectionTools().toTypedArray()) @@ -44,4 +47,18 @@ class SvelteTypeScriptHighlightingTest : BasePlatformTestCase() { ) myFixture.testHighlighting() } + + fun testTsconfigDirectAncestorDiscovery() { + val base = basePath + "/" + getTestName(true) + myFixture.configureByFiles("$base/src/App.svelte", "$base/tsconfig.json") + + myFixture.testHighlighting() + } + + fun testTsconfigIndirectAncestorDiscovery() { + val base = basePath + "/" + getTestName(true) + myFixture.configureByFiles("$base/src/nested/Child.svelte", "$base/tsconfig.json") + + myFixture.testHighlighting() + } } diff --git a/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigDirectAncestorDiscovery/src/App.svelte b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigDirectAncestorDiscovery/src/App.svelte new file mode 100644 index 00000000..cff813a3 --- /dev/null +++ b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigDirectAncestorDiscovery/src/App.svelte @@ -0,0 +1,4 @@ + diff --git a/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigDirectAncestorDiscovery/tsconfig.json b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigDirectAncestorDiscovery/tsconfig.json new file mode 100644 index 00000000..dadb5f97 --- /dev/null +++ b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigDirectAncestorDiscovery/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "target": "es2017", + /** + Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript + to enforce using `import type` instead of `import` for Types. + */ + "importsNotUsedAsValues": "error", + "isolatedModules": true, + /** + To have warnings/errors of the Svelte compiler at the correct position, + enable source maps by default. + */ + "sourceMap": true, + /** Requests the runtime types from the svelte modules by default. Needed for TS files or else you get errors. */ + "types": ["svelte"], + "lib": [ + "dom", + "ES2020" + ], + "strict": false, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], +} diff --git a/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigIndirectAncestorDiscovery/src/nested/Child.svelte b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigIndirectAncestorDiscovery/src/nested/Child.svelte new file mode 100644 index 00000000..1a6f3007 --- /dev/null +++ b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigIndirectAncestorDiscovery/src/nested/Child.svelte @@ -0,0 +1,4 @@ + diff --git a/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigIndirectAncestorDiscovery/tsconfig.json b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigIndirectAncestorDiscovery/tsconfig.json new file mode 100644 index 00000000..dadb5f97 --- /dev/null +++ b/src/test/resources/dev/blachut/svelte/lang/codeInsight/tsHighlighting/tsconfigIndirectAncestorDiscovery/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "target": "es2017", + /** + Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript + to enforce using `import type` instead of `import` for Types. + */ + "importsNotUsedAsValues": "error", + "isolatedModules": true, + /** + To have warnings/errors of the Svelte compiler at the correct position, + enable source maps by default. + */ + "sourceMap": true, + /** Requests the runtime types from the svelte modules by default. Needed for TS files or else you get errors. */ + "types": ["svelte"], + "lib": [ + "dom", + "ES2020" + ], + "strict": false, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], +}