tomblachut / svelte-intellij

Svelte components in WebStorm and friends
MIT License
485 stars 38 forks source link

Fix reactive declarations in TypeScript #168

Closed tomblachut closed 4 years ago

tomblachut commented 4 years ago

Fixes #167. I only did quick checkup, need to do more regression testing before merging, I don't have more time now unfortunately.

@anstarovoyt how bad do you think this solution is? I though maybe you could change actual TypeScriptReferenceExpressionResolver a bit in WS 2020.3 so this TypeScriptReferenceExpressionResolver2 could be deleted later.

anstarovoyt commented 4 years ago

I will take a look on Friday, but in general, I have a couple different ideas:

  1. We have an extension point to contribute new references (and resolution for ref. expression)
  2. We have some methods in FrameworkIndexingHandler that allows contributing new elements in the resolution
tomblachut commented 4 years ago

okay, sounds definitely better

anstarovoyt commented 4 years ago

Ok, I spent some time investigating the problem, and looks like the simplest solution is

   class SvelteTypeScriptReferenceExpressionResolver(...

    override fun resolve(expression: JSReferenceExpressionImpl, incompleteCode: Boolean): Array<ResolveResult> {
        val resolveImplicits = resolveImplicits(expression)
        if (resolveImplicits.isNotEmpty()) return resolveImplicits

        val resolved = super.resolve(expression, incompleteCode)
        if (resolved.size == 0 && expression.qualifier == null) {
            val sink = ResolveResultSink(myRef, myReferencedName, false, incompleteCode)
            val localProcessor = createLocalResolveProcessor(sink)
            JSReferenceExpressionImpl.doProcessLocalDeclarations(myRef,myQualifier, localProcessor as ResolveProcessor?, false, false, null as Boolean?)
            val jsElement = (localProcessor as SinkResolveProcessor<*>).result
            val labeledStatement = jsElement.parentOfType<JSLabeledStatement>()
            if (labeledStatement != null && labeledStatement.label == REACTIVE_LABEL) {
                return localProcessor.resultsAsResolveResults
            }
        }
        return resolved
    }

    override fun createLocalResolveProcessor(sink: ResolveResultSink): SinkResolveProcessor<ResolveResultSink> {
        return SvelteReactiveDeclarationsUtil.SvelteSinkResolveProcessor(myReferencedName, myRef, sink)
    }

I haven't tried but in general, it should work

tomblachut commented 4 years ago

I think this will break if you for some reason shadow a global

e.g.

  $: EventTarget = 1;
anstarovoyt commented 4 years ago

sounds weird, I'd prefer to keep the solution until the first request :) But you can also change the order (first try to check locals). doProcessLocalDeclarations It is a cheap operation anyway

anstarovoyt commented 4 years ago
tomblachut commented 4 years ago

Ok this sounds like a good middle ground 👍 I'll delete copied file and test your snippet later

tomblachut commented 4 years ago

@anstarovoyt your snippet works nicely, thanks!