Skip to content

Commit c9703cd

Browse files
committed
解决kotlin代码重排的一个严重问题
1 parent 287d6cd commit c9703cd

14 files changed

Lines changed: 49 additions & 391 deletions

AegisCodeCheckPlugin.zip

383 Bytes
Binary file not shown.

resources/META-INF/plugin.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
and it supports both java and kotlin.<br>
1414
Otherwise, it provided some additional features, such as:
1515
<ul>
16+
<li>rearrange kotlin source code when reformatting like java</li>
1617
<li>rearrange tag attributes for .vue files when reformatting</li>
1718
<li>add gutters for mybatis mapper interfaces and mapping xml files,
1819
you can jump from the interface methods to the mapping file tag or the opposite,
@@ -39,7 +40,7 @@
3940
<extensions defaultExtensionNs="com.intellij">
4041
<postStartupActivity implementation="com.wuhao.code.check.PostStart"/>
4142
<lang.rearranger language="kotlin"
42-
implementationClass="com.wuhao.code.check.style.arrangement.KotlinCodeRearrangeProcessor"/>
43+
implementationClass="com.wuhao.code.check.style.arrangement.KotlinRearranger"/>
4344
<completion.contributor
4445
implementationClass="com.wuhao.code.check.completion.SpringBootConfigValueInjectCodeCompletion"
4546
language="JAVA" order="FIRST"/>

src/com/wuhao/code/check/CommonConstants.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fun getPsiElementFactory(element: PsiElement): PsiElementFactoryImpl {
6060
/**
6161
* 全局日志
6262
*/
63-
val LOG = Logger.getLogger("plugin")
63+
val LOG: Logger = Logger.getLogger("plugin")
6464

6565
/**
6666
* kotlin的修饰符

src/com/wuhao/code/check/processors/FixJavaBlankLineProcessor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class FixJavaBlankLineProcessor : PostFormatProcessor {
5050
if (element is PsiField) {
5151
val nextField = element.getNextSiblingIgnoringWhitespace()
5252
val prevField = element.getPrevSiblingIgnoringWhitespaceAndComments()
53-
if(prevField !is PsiField) {
53+
if (prevField !is PsiField) {
5454
fixBlankLineBefore(element, 2, factory)
5555
}
5656
if (nextField is PsiField) {

src/com/wuhao/code/check/processors/FixJavaElementOrder.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ class FixJavaElementOrder : PostFormatProcessor {
7979

8080
/**
8181
* 获取java修饰符的权重
82-
* @param modifier 修饰符
8382
* @return 权重值
8483
*/
8584
private fun JvmModifier.getWeight(): Int {

src/com/wuhao/code/check/style/arrangement/KotlinArrangementEntryDependencyInfo.kt

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/com/wuhao/code/check/style/arrangement/KotlinArrangementOverriddenMethodsInfo.kt

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/com/wuhao/code/check/style/arrangement/KotlinArrangementParseInfo.kt

Lines changed: 0 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,6 @@
33
*/
44
package 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
136
import org.jetbrains.kotlin.psi.KtNamedFunction
147
import org.jetbrains.kotlin.psi.KtProperty
158
import java.util.*
@@ -22,136 +15,22 @@ import kotlin.collections.LinkedHashMap
2215
class 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

src/com/wuhao/code/check/style/arrangement/KotlinArrangementVisitor.kt

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class KotlinArrangementVisitor(private val myInfo: KotlinArrangementParseInfo,
6262

6363
init {
6464
myGroupingRules = getGroupingRules(settings)
65-
myMethodBodyProcessor = MethodBodyProcessor(myInfo)
65+
myMethodBodyProcessor = MethodBodyProcessor()
6666
mySectionDetector = ArrangementSectionDetector(myDocument, settings) { data ->
6767
val range = data.textRange
6868
val entry = KotlinSectionArrangementEntry(current, data.token, range, data.text, true)
@@ -87,19 +87,7 @@ class KotlinArrangementVisitor(private val myInfo: KotlinArrangementParseInfo,
8787
mySectionDetector.processComment(comment)
8888
}
8989

90-
private val visitCache = arrayListOf<PsiElement>()
91-
override fun visitElement(element: PsiElement) {
92-
if (visitCache.contains(element)) {
93-
return
94-
}
95-
visitCache.add(element)
96-
super.visitElement(element)
97-
element.children.forEach { child ->
98-
this.visitElement(child)
99-
}
100-
}
101-
102-
override fun visitClass(clazz: KtClass) {
90+
override fun visitClass(clazz: KtClass,data:Any?) {
10391
val isSectionCommentsDetected = registerSectionComments(clazz)
10492
val range = if (isSectionCommentsDetected) getElementRangeWithoutComments(clazz) else clazz.textRange
10593
var type = CLASS
@@ -176,7 +164,10 @@ class KotlinArrangementVisitor(private val myInfo: KotlinArrangementParseInfo,
176164
}
177165
}
178166

179-
override fun visitProperty(property: KtProperty) {
167+
override fun visitProperty(property: KtProperty, data: Any?) {
168+
if (property.parent !is KtClassBody){
169+
return
170+
}
180171
val isSectionCommentsDetected = registerSectionComments(property)
181172
// There is a possible case that more than one field is declared for the same type like 'int i, j;'. We want to process only
182173
// the first one then.
@@ -261,18 +252,20 @@ class KotlinArrangementVisitor(private val myInfo: KotlinArrangementParseInfo,
261252
return element.textRange.endOffset
262253
}
263254

264-
override fun visitClassInitializer(initializer: KtClassInitializer) {
255+
override fun visitClassInitializer(initializer: KtClassInitializer,data: Any?) {
265256
val entry = createNewEntry(initializer, initializer.textRange, INIT_BLOCK, null, true) ?: return
266257
parseModifiers(initializer.modifierList, entry)
267258
}
268259

269-
override fun visitFunction(function: KtNamedFunction) {
260+
override fun visitNamedFunction(function: KtNamedFunction, data: Any?) {
261+
if (function.parent !is KtClassBody){
262+
return
263+
}
270264
val isSectionCommentsDetected = registerSectionComments(function)
271265
val range = if (isSectionCommentsDetected)
272266
getElementRangeWithoutComments(function)
273267
else
274268
function.textRange
275-
276269
val type = METHOD
277270
val entry = createNewEntry(function, range, type, function.name, true) ?: return
278271
processEntry(entry, function, function.bodyExpression)
@@ -292,40 +285,17 @@ class KotlinArrangementVisitor(private val myInfo: KotlinArrangementParseInfo,
292285
* @author 吴昊
293286
* @since 1.2.6
294287
*/
295-
private class MethodBodyProcessor internal constructor(private val myInfo: KotlinArrangementParseInfo) :
288+
private class MethodBodyProcessor internal constructor() :
296289
JavaRecursiveElementVisitor() {
297290
private var myBaseMethod: KtNamedFunction? = null
298291

299-
300-
override fun visitMethodCallExpression(psiMethodCallExpression: PsiMethodCallExpression) {
301-
val reference = psiMethodCallExpression.methodExpression.reference ?: return
302-
val e = reference.resolve()
303-
if (e is KtNamedFunction) {
304-
assert(myBaseMethod != null)
305-
val m = e as KtNamedFunction?
306-
if (m!!.parent === myBaseMethod!!.parent) {
307-
myInfo.registerMethodCallDependency(myBaseMethod!!, m!!)
308-
}
309-
}
310-
311-
// We process all method call expression children because there is a possible case like below:
312-
// new Runnable() {
313-
// void test();
314-
// }.visit();
315-
// Here we want to process that 'Runnable.visit()' implementation.
316-
super.visitMethodCallExpression(psiMethodCallExpression)
317-
}
318-
319-
320292
internal fun setBaseMethod(baseMethod: KtNamedFunction?): Boolean {
321293
if (baseMethod == null || myBaseMethod == null) {
322294
myBaseMethod = baseMethod
323295
return true
324296
}
325297
return false
326298
}
327-
328-
329299
}
330300

331301
companion object {

src/com/wuhao/code/check/style/arrangement/KotlinElementArrangementEntry.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ open class KotlinElementArrangementEntry(parent: ArrangementEntry?,
3333
range: TextRange,
3434
type: ArrangementSettingsToken,
3535
name: String?,
36-
canBeMatched: Boolean) : this(parent, range.startOffset, range.endOffset, type, name, canBeMatched) {
37-
}
36+
canBeMatched: Boolean) : this(parent, range.startOffset, range.endOffset, type, name, canBeMatched)
3837

3938
init {
4039
myTypes.add(type)

0 commit comments

Comments
 (0)