33 */
44package com.wuhao.code.check.style.arrangement
55
6- import com.intellij.openapi.util.Pair
7- import com.intellij.psi.codeStyle.arrangement.ArrangementEntryDependencyInfo
8- import com.intellij.util.containers.ContainerUtil
9- import com.intellij.util.containers.ContainerUtilRt
10- import com.intellij.util.containers.Stack
11- import gnu.trove.TObjectIntHashMap
12- import org.jetbrains.kotlin.psi.KtClass
136import org.jetbrains.kotlin.psi.KtNamedFunction
147import org.jetbrains.kotlin.psi.KtProperty
158import java.util.*
@@ -22,136 +15,22 @@ import kotlin.collections.LinkedHashMap
2215class KotlinArrangementParseInfo {
2316
2417 private val myEntries = ArrayList <KotlinElementArrangementEntry >()
25- private val myMethodDependencyRoots = ArrayList <KotlinArrangementEntryDependencyInfo >()
26- private val myMethodDependencies = HashMap <KtNamedFunction , MutableSet <KtNamedFunction / * dependencies * / >>()
2718 private val myMethodEntriesMap = HashMap <KtNamedFunction , KotlinElementArrangementEntry >()
28- private val myOverriddenMethods = LinkedHashMap <KtClass , MutableList <Pair <KtNamedFunction / * overridden* / ,
29- KtNamedFunction / * overriding* / >>>()
30- private val myTmpMethodDependencyRoots = LinkedHashSet <KtNamedFunction >()
31- private val myDependentMethods = HashSet <KtNamedFunction >()
3219 private val myFields = LinkedHashMap <KtProperty , KotlinElementArrangementEntry >()
33- private val myFieldDependencies = HashMap <KtProperty , Set <KtProperty >>()
34- private var myRebuildMethodDependencies: Boolean = false
3520
3621 val entries: List <KotlinElementArrangementEntry >
3722 get() = myEntries
3823
39- /* *
40- * @return list of method dependency roots, i.e. there is a possible case that particular method
41- * [calls another method][ArrangementEntryDependencyInfo.getDependentEntriesInfos], it calls other methods
42- * and so forth
43- */
44- val methodDependencyRoots: List <KotlinArrangementEntryDependencyInfo >
45- get() {
46- if (myRebuildMethodDependencies) {
47- myMethodDependencyRoots.clear()
48- val cache = HashMap <KtNamedFunction , KotlinArrangementEntryDependencyInfo >()
49- for (method in myTmpMethodDependencyRoots) {
50- val info = buildMethodDependencyInfo(method, cache)
51- if (info != null ) {
52- myMethodDependencyRoots.add(info)
53- }
54- }
55- myRebuildMethodDependencies = false
56- }
57- return myMethodDependencyRoots
58- }
59-
60- val overriddenMethods: List <KotlinArrangementOverriddenMethodsInfo >
61- get() {
62- val result = ArrayList <KotlinArrangementOverriddenMethodsInfo >()
63- val weights = TObjectIntHashMap <KtNamedFunction >()
64- val comparator = Comparator <Pair <KtNamedFunction , KtNamedFunction >> { o1, o2 ->
65- weights.get(o1.first) - weights.get(o2
66- .first)
67- }
68- for ((key, value) in myOverriddenMethods) {
69- val info = KotlinArrangementOverriddenMethodsInfo (key.name!! )
70- weights.clear()
71- ContainerUtil .sort(value, comparator)
72- for (pair in value) {
73- val overridingMethodEntry = myMethodEntriesMap[pair.second]
74- if (overridingMethodEntry != null ) {
75- info.addMethodEntry(overridingMethodEntry)
76- }
77- }
78- if (! info.methodEntries.isEmpty()) {
79- result.add(info)
80- }
81- }
82-
83- return result
84- }
85-
86- val fieldDependencyRoots: List <KotlinArrangementEntryDependencyInfo >
87- get() = KotlinFieldDependenciesManager (myFieldDependencies, myFields).roots
88-
89- val fields: Collection <KotlinElementArrangementEntry >
90- get() = myFields.values
91-
9224 fun addEntry (entry : KotlinElementArrangementEntry ) {
9325 myEntries.add(entry)
9426 }
9527
96-
97- private fun buildMethodDependencyInfo (
98- method : KtNamedFunction ,
99- cache : MutableMap <KtNamedFunction , KotlinArrangementEntryDependencyInfo >): KotlinArrangementEntryDependencyInfo ? {
100- val entry = myMethodEntriesMap[method] ? : return null
101- val result = KotlinArrangementEntryDependencyInfo (entry)
102- val toProcess = Stack <Pair <KtNamedFunction , KotlinArrangementEntryDependencyInfo >>()
103- toProcess.push(Pair .create(method, result))
104- val usedMethods = ContainerUtilRt .newHashSet<KtNamedFunction >()
105- while (! toProcess.isEmpty()) {
106- val pair = toProcess.pop()
107- val dependentMethods = myMethodDependencies[pair.first] ? : continue
108- usedMethods.add(pair.first)
109- for (dependentMethod in dependentMethods) {
110- if (usedMethods.contains(dependentMethod)) {
111- // Prevent cyclic dependencies.
112- return null
113- }
114- val dependentEntry = myMethodEntriesMap[dependentMethod] ? : continue
115- val dependentMethodInfo: KotlinArrangementEntryDependencyInfo ? = cache[dependentMethod]
116- if (dependentMethodInfo == null ) {
117- cache[dependentMethod] = KotlinArrangementEntryDependencyInfo (dependentEntry)
118- }
119- val dependentPair = Pair .create<KtNamedFunction , KotlinArrangementEntryDependencyInfo >(dependentMethod,
120- dependentMethodInfo)
121- pair.second.addDependentEntryInfo(dependentPair.second)
122- toProcess.push(dependentPair)
123- }
124- }
125- return result
126- }
127-
128-
12928 fun onMethodEntryCreated (method : KtNamedFunction , entry : KotlinElementArrangementEntry ) {
13029 myMethodEntriesMap[method] = entry
13130 }
13231
13332 fun onFieldEntryCreated (field : KtProperty , entry : KotlinElementArrangementEntry ) {
13433 myFields[field] = entry
13534 }
136-
137- /* *
138- * Is expected to be called when new method dependency is detected. Here given `'base method'` calls
139- * `'dependent method'`.
140- */
141- fun registerMethodCallDependency (caller : KtNamedFunction , callee : KtNamedFunction ) {
142- myTmpMethodDependencyRoots.remove(callee)
143- if (! myDependentMethods.contains(caller)) {
144- myTmpMethodDependencyRoots.add(caller)
145- }
146- myDependentMethods.add(callee)
147- val methods: MutableSet <KtNamedFunction >? = myMethodDependencies[caller]
148- if (methods == null ) {
149- myMethodDependencies[caller] = LinkedHashSet ()
150- }
151- if (! methods!! .contains(callee)) {
152- methods.add(callee)
153- }
154- myRebuildMethodDependencies = true
155- }
15635}
15736
0 commit comments