@@ -19,7 +19,6 @@ package org.intellij.clojure.psi.impl
19
19
20
20
import com.intellij.extapi.psi.PsiFileBase
21
21
import com.intellij.lang.Language
22
- import com.intellij.openapi.util.Key
23
22
import com.intellij.openapi.util.TextRange
24
23
import com.intellij.openapi.util.text.StringUtil
25
24
import com.intellij.openapi.vfs.VirtualFileWithId
@@ -32,6 +31,7 @@ import com.intellij.util.SmartList
32
31
import com.intellij.util.containers.JBIterable
33
32
import com.intellij.util.containers.JBTreeTraverser
34
33
import com.intellij.util.containers.TreeTraversal
34
+ import com.intellij.util.indexing.FileBasedIndex
35
35
import org.intellij.clojure.ClojureConstants
36
36
import org.intellij.clojure.editor.arguments
37
37
import org.intellij.clojure.lang.ClojureFileType
@@ -44,7 +44,7 @@ import org.intellij.clojure.util.*
44
44
import java.lang.ref.SoftReference
45
45
import java.util.*
46
46
47
- private val EXPLICIT_RESOLVE_KEY : Key < SymKey > = Key .create( " EXPLICIT_RESOLVE_KEY " )
47
+ private data class ResolveTo ( val key : SymKey )
48
48
private val ALL : Set <String > = setOf (" * all *" )
49
49
val PRIVATE_META = " #private"
50
50
val TYPE_META = " #typeHint"
@@ -196,8 +196,8 @@ class CFileImpl(viewProvider: FileViewProvider, language: Language) :
196
196
val namespace = namespace
197
197
val forceAlias = state.get(ALIAS_KEY )
198
198
var langKindNSVisited = false
199
+ val thisImport = this .state.imports.find { it.range.contains(placeOffset) }
199
200
val imports = importsAtOffset(placeOffset, dialect)
200
- val insideImport = imports.find { it.range.contains(placeOffset) } != null
201
201
for (import in imports.flatMap { it.imports }) {
202
202
if (refText == null || isQualifier) {
203
203
if (! import.isPlatform && import.aliasSym != null ) {
@@ -222,7 +222,7 @@ class CFileImpl(viewProvider: FileViewProvider, language: Language) :
222
222
langKindNSVisited = langKindNSVisited || dialect.coreNs == import.namespace
223
223
val refersByDefault = import.nsType == " refer" || import.nsType == " refer-clojure" || import.nsType == " use"
224
224
if (! processNamespace(import.namespace, dialect, state,
225
- if (insideImport ) processor
225
+ if (thisImport != null && thisImport.imports.contains(import) ) processor
226
226
else object : PsiScopeProcessor by processor {
227
227
override fun execute (element : PsiElement , state : ResolveState ): Boolean {
228
228
val name = element.asCTarget?.key?.name ? : element.asDef?.def?.name ? : return true
@@ -269,11 +269,10 @@ class CFileImpl(viewProvider: FileViewProvider, language: Language) :
269
269
.associateBy({ it.namespace }, { it.alias })
270
270
}
271
271
272
-
273
272
internal fun processPrecomputedDeclarations (refText : String? , place : CSymbol , dialect : Dialect ,
274
273
service : ClojureDefinitionService , state : ResolveState ,
275
274
processor : PsiScopeProcessor ): Boolean {
276
- val key = EXPLICIT_RESOLVE_KEY .get( place) ? : return true
275
+ val key = (( place as ? CComposite )?.data as ? ResolveTo )?.key ? : return true
277
276
val target = when (key.type) {
278
277
" java package" ->
279
278
if (dialect == Dialect .CLJS ) return processor.skipResolve()
@@ -289,12 +288,20 @@ class CFileImpl(viewProvider: FileViewProvider, language: Language) :
289
288
if (target != null ) {
290
289
if (key.type == " def" ) {
291
290
if (! processNamespace(key.namespace, dialect, state, processor, this )) return false
292
- return processSpecialForms(dialect, refText, place, service, state, processor)
291
+ if (key.namespace == dialect.coreNs) {
292
+ if (! processSpecialForms(dialect, refText, place, service, state, processor)) return false
293
+ }
294
+ }
295
+ else if (refText != null ) {
296
+ if (! processor.execute(target, state)) return false
297
+ }
298
+ else if (key.type == " ns" ) {
299
+ FileBasedIndex .getInstance().processAllKeys(NS_INDEX , { ns ->
300
+ processor.execute(service.getNamespace(ns), state)
301
+ }, project)
293
302
}
294
- if (refText != null ) return processor.execute(target, state)
295
- return true
296
303
}
297
- return true
304
+ return false
298
305
}
299
306
}
300
307
@@ -504,7 +511,7 @@ private class RoleHelper {
504
511
setData(e, ns ? : " " )
505
512
}
506
513
507
- fun processNSElement (e : CListBase ) {
514
+ private fun processNSElement (e : CListBase ) {
508
515
e.cljTraverser().filter(CKeywordBase ::class .java).onEach { processKeyword(it) }
509
516
nsReader.processElement(e)
510
517
}
@@ -585,7 +592,7 @@ private class NSReader(val helper: RoleHelper) {
585
592
val name = o.name
586
593
val qualifiedName = name.withPackage(prefix)
587
594
classes.add(qualifiedName)
588
- o.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (name, prefix, " java class" ))
595
+ setResolveTo(o , SymKey (name, prefix, " java class" ))
589
596
}
590
597
for (item in iterator) {
591
598
when (item) {
@@ -599,7 +606,7 @@ private class NSReader(val helper: RoleHelper) {
599
606
addClass(it as ? CSymbol ? : return @forEach, packageName)
600
607
if (anyClass == " " ) anyClass = it.name
601
608
}
602
- packageSym.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (anyClass, packageName, " java package" ))
609
+ setResolveTo(packageSym , SymKey (anyClass, packageName, " java package" ))
603
610
}
604
611
}
605
612
}
@@ -613,7 +620,7 @@ private class NSReader(val helper: RoleHelper) {
613
620
val nsSym = iterator.safeNext() as ? CSymbol
614
621
val namespace = nsSym?.name ? : " "
615
622
setData(aliasSym, Role .NAME )
616
- nsSym?.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (namespace, " " , " ns" ))
623
+ setResolveTo(nsSym , SymKey (namespace, " " , " ns" ))
617
624
return listOf (Import (" alias" , namespace, aliasSym.name, aliasSym))
618
625
}
619
626
@@ -639,17 +646,17 @@ private class NSReader(val helper: RoleHelper) {
639
646
}
640
647
val namespace = if (forcedNamespace) nsPrefix else (nsSym?.name?.withPackage(nsPrefix) ? : " " )
641
648
val alias = aliasSym?.name ? : " "
642
- nsSym?.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (namespace, " " , " ns" ))
643
- aliasSym?.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (alias, namespace, " alias" ))
649
+ setResolveTo(nsSym , SymKey (namespace, " " , " ns" ))
650
+ setResolveTo(aliasSym , SymKey (alias, namespace, " alias" ))
644
651
fun CPForm?.toNames () = traverser.withRoot(this ).filter(CSymbol ::class .java)
645
- .transform { sym -> sym.name.also { sym.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (it, namespace, " def" )) } }.toSet()
652
+ .transform { sym -> sym.name.also { setResolveTo(sym , SymKey (it, namespace, " def" )) } }.toSet()
646
653
647
654
val import = Import (nsType, namespace, alias, aliasSym,
648
655
(refer as ? CPForm )?.toNames() ? : (refer as ? CKeyword )?.let { if (it.name == " all" ) ALL else null } ? : emptySet(),
649
656
only.toNames(), exclude.toNames(),
650
657
rename?.split(2 , true )?.reduce(HashMap ()) { map, o ->
651
658
if (o.size == 2 ) map.put(o[0 ].name,
652
- o[1 ].also { it.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (it.name, namespace, " alias" )) }); map
659
+ o[1 ].also { setResolveTo(it , SymKey (it.name, namespace, " alias" )) }); map
653
660
} ? : emptyMap())
654
661
return import
655
662
}
@@ -662,7 +669,7 @@ private class NSReader(val helper: RoleHelper) {
662
669
when (item) {
663
670
is CSymbol -> item.name.withPackage(nsPrefix).let { ns ->
664
671
result.add(Import (nsType, ns, " " , null ))
665
- item.putUserData( EXPLICIT_RESOLVE_KEY , SymKey (ns, " " , " ns" ))
672
+ setResolveTo(item , SymKey (ns, " " , " ns" ))
666
673
}
667
674
is CVec -> result.addAll(readNSElement_refer(nsPrefix, traverser.iterate(item), traverser, nsType).asListOrEmpty())
668
675
}
@@ -712,6 +719,10 @@ private fun setData(o: PsiElement?, data: Any?) {
712
719
if (o is CComposite ) o.dataImpl = data
713
720
}
714
721
722
+ private fun setResolveTo (o : CSymbol ? , key : SymKey ) {
723
+ setData(o, ResolveTo (key))
724
+ }
725
+
715
726
fun PsiElement?.rcTraverser (rcKey : String ) = cljTraverser()
716
727
.forceDisregard { e ->
717
728
val r = e.fastRole
0 commit comments