eb90ba4a97713d53700dd2935d754e3cda4c2d65
[idea/community.git] / jps / jps-builders / testSrc / org / jetbrains / references / ReferenceIndexTestBase.kt
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.references
17
18 import com.intellij.openapi.util.io.FileUtil
19 import com.intellij.openapi.vfs.CharsetToolkit
20 import com.intellij.testFramework.UsefulTestCase
21 import com.intellij.util.PathUtil
22 import com.sun.tools.javac.util.Convert
23 import junit.framework.TestCase
24 import org.jetbrains.jps.backwardRefs.BackwardReferenceIndexWriter
25 import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator
26 import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex
27 import org.jetbrains.jps.backwardRefs.LightUsage
28 import org.jetbrains.jps.builders.JpsBuildTestCase
29 import org.jetbrains.jps.builders.TestProjectBuilderLogger
30 import org.jetbrains.jps.builders.logging.BuildLoggingManager
31 import java.io.File
32
33 abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
34   public override fun setUp() {
35     super.setUp()
36     System.setProperty(BackwardReferenceIndexWriter.PROP_KEY, true.toString())
37   }
38
39   public override fun tearDown() {
40     super.tearDown()
41     System.clearProperty(BackwardReferenceIndexWriter.PROP_KEY)
42   }
43
44   protected fun assertIndexOnRebuild(vararg files: String) {
45     var representativeFile: String? = null
46     for (file in files) {
47       val addedFile = addFile(file)
48       if (representativeFile == null) {
49         representativeFile = addedFile
50       }
51     }
52     addModule("m", PathUtil.getParentPath(representativeFile!!))
53     rebuildAllModules()
54     assertIndexEquals("initialIndex.txt")
55   }
56
57   protected fun renameFile(fileToRename: String, newName: String) {
58     rename(orCreateProjectDir.path + "/m/" + fileToRename, newName)
59   }
60
61   protected fun changeFileContent(name: String, changesSourceFile: String) {
62     changeFile("m/" + name, FileUtil.loadFile(File(testDataRootPath + "/" + getTestName(true) + "/" + changesSourceFile), CharsetToolkit.UTF8_CHARSET))
63   }
64
65   protected fun addFile(name: String): String {
66     return createFile("m/" + name, FileUtil.loadFile(File(getTestDataPath() + name), CharsetToolkit.UTF8_CHARSET))
67   }
68
69
70   protected fun assertIndexEquals(expectedIndexDumpFile: String) {
71     val expectedIndex = FileUtil.loadFile(File(testDataRootPath + "/" + getTestName(true) + "/" + expectedIndexDumpFile), CharsetToolkit.UTF8_CHARSET)
72     val actualIndex = indexAsText()
73     TestCase.assertTrue(String.CASE_INSENSITIVE_ORDER.compare(expectedIndex, actualIndex) == 0)
74   }
75
76   protected fun indexAsText(): String {
77     val pd = createProjectDescriptor(BuildLoggingManager(TestProjectBuilderLogger()))
78     val manager = pd.dataManager
79     val buildDir = manager.dataPaths.dataStorageRoot
80     val index = CompilerBackwardReferenceIndex(buildDir)
81
82     try {
83       val fileEnumerator = index.filePathEnumerator
84       val nameEnumerator = index.byteSeqEum
85
86       val result = StringBuilder()
87       result.append("Backward Hierarchy:\n")
88       val hierarchyText = mutableListOf<String>()
89       index.backwardHierarchyMap.forEachEntry { superClass, inheritors ->
90         val superClassName = superClass.asText(nameEnumerator)
91         val inheritorsText = mutableListOf<String>()
92         inheritors.forEach { id ->
93           inheritorsText.add(id.asText(nameEnumerator))
94           true
95         }
96         inheritorsText.sort()
97         hierarchyText.add(superClassName + " -> " + inheritorsText.joinToString(separator = " "))
98         true
99       }
100       hierarchyText.sort()
101       result.append(hierarchyText.joinToString(separator = "\n"))
102
103       result.append("\n\nBackward References:\n")
104       val referencesText = mutableListOf<String>()
105       index.backwardReferenceMap.forEachEntry { usage, files ->
106         val referents = mutableListOf<String>()
107         files.forEach { id ->
108           val file = File(fileEnumerator.valueOf(id))
109           val fileName = FileUtil.getNameWithoutExtension(file)
110           referents.add(fileName)
111         }
112         referents.sort()
113         referencesText.add(usage.asText(nameEnumerator) + " in " + referents.joinToString(separator = " "))
114         true
115       }
116       referencesText.sort()
117       result.append(referencesText.joinToString(separator = "\n"))
118
119       result.append("\n\nClass Definitions:\n")
120       val classDefs = mutableListOf<String>()
121       index.backwardClassDefinitionMap.forEachEntry { usage, files ->
122         val definitionFiles = mutableListOf<String>()
123         files.forEach { id ->
124           val file = File(fileEnumerator.valueOf(id))
125           val fileName = FileUtil.getNameWithoutExtension(file)
126           definitionFiles.add(fileName)
127         }
128         definitionFiles.sort()
129         classDefs.add(usage.asText(nameEnumerator) + " in " + definitionFiles.joinToString(separator = " "))
130         true
131       }
132       classDefs.sort()
133       result.append(classDefs.joinToString(separator = "\n"))
134
135       return result.toString()
136     } finally {
137       index.close()
138     }
139   }
140
141   private fun getTestDataPath() = testDataRootPath + "/" + getTestName(true) + "/"
142
143   private fun Int.asName(byteArrayEnumerator: ByteArrayEnumerator): String = Convert.utf2string(
144       byteArrayEnumerator.valueOf(this))
145
146   private fun CompilerBackwardReferenceIndex.LightDefinition.asText(byteArrayEnumerator: ByteArrayEnumerator) = this.usage.asText(byteArrayEnumerator)
147
148   private fun LightUsage.asText(byteArrayEnumerator: ByteArrayEnumerator): String =
149       when (this) {
150         is LightUsage.LightMethodUsage -> this.owner.name.asName(byteArrayEnumerator) + "." + this.name.asName(
151             byteArrayEnumerator) + "(" + this.parameterCount + ")"
152         is LightUsage.LightFieldUsage -> this.owner.name.asName(byteArrayEnumerator) + "." + this.name.asName(byteArrayEnumerator)
153         is LightUsage.LightClassUsage -> this.name.asName(byteArrayEnumerator)
154         is LightUsage.LightFunExprUsage -> "fun_expr(" + this.name.asName(byteArrayEnumerator) + ")"
155         else -> throw UnsupportedOperationException()
156       }
157 }