javac ast indices: when java file contains >1 top declaration classes only one was...
[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.openapi.vfs.VfsUtil
21 import com.intellij.util.PathUtil
22 import com.intellij.util.io.PersistentStringEnumerator
23 import com.sun.tools.javac.util.Convert
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     assertSameLinesWithFile(testDataRootPath + "/" + getTestName(true) + "/" + expectedIndexDumpFile, indexAsText())
72   }
73
74   protected fun indexAsText(): String {
75     val pd = createProjectDescriptor(BuildLoggingManager(TestProjectBuilderLogger()))
76     val manager = pd.dataManager
77     val buildDir = manager.dataPaths.dataStorageRoot
78     val index = CompilerBackwardReferenceIndex(buildDir)
79
80     try {
81       val fileEnumerator = index.filePathEnumerator
82       val nameEnumerator = index.byteSeqEum
83
84       val result = StringBuilder()
85       result.append("Backward Hierarchy:\n")
86       val hierarchyText = mutableListOf<String>()
87       index.backwardHierarchyMap.forEachEntry { superClass, inheritors ->
88         val superClassName = superClass.asText(nameEnumerator)
89         val inheritorsText = mutableListOf<String>()
90         inheritors.forEach { id ->
91           inheritorsText.add(id.asText(nameEnumerator))
92         }
93         inheritorsText.sort()
94         hierarchyText.add(superClassName + " -> " + inheritorsText.joinToString(separator = " "))
95         true
96       }
97       hierarchyText.sort()
98       result.append(hierarchyText.joinToString(separator = "\n"))
99
100       result.append("\n\nBackward References:\n")
101       val referencesText = mutableListOf<String>()
102       index.backwardReferenceMap.forEachEntry { usage, files ->
103         val referents = mutableListOf<String>()
104         files.forEach { id ->
105           referents.add(id.asFileName(fileEnumerator))
106         }
107         referents.sort()
108         referencesText.add(usage.asText(nameEnumerator) + " in " + referents.joinToString(separator = " "))
109         true
110       }
111       referencesText.sort()
112       result.append(referencesText.joinToString(separator = "\n"))
113
114       result.append("\n\nClass Definitions:\n")
115       val classDefs = mutableListOf<String>()
116       index.backwardClassDefinitionMap.forEachEntry { usage, files ->
117         val definitionFiles = mutableListOf<String>()
118         files.forEach { id ->
119           definitionFiles.add(id.asFileName(fileEnumerator))
120         }
121         definitionFiles.sort()
122         classDefs.add(usage.asText(nameEnumerator) + " in " + definitionFiles.joinToString(separator = " "))
123         true
124       }
125       classDefs.sort()
126       result.append(classDefs.joinToString(separator = "\n"))
127
128       return result.toString()
129     } finally {
130       index.close()
131     }
132   }
133
134   private fun getTestDataPath() = testDataRootPath + "/" + getTestName(true) + "/"
135
136   private fun Int.asName(byteArrayEnumerator: ByteArrayEnumerator): String = Convert.utf2string(byteArrayEnumerator.valueOf(this))
137
138   private fun CompilerBackwardReferenceIndex.LightDefinition.asText(byteArrayEnumerator: ByteArrayEnumerator) = this.usage.asText(byteArrayEnumerator)
139
140   private fun LightUsage.asText(byteArrayEnumerator: ByteArrayEnumerator): String =
141       when (this) {
142         is LightUsage.LightMethodUsage -> this.owner.name.asName(byteArrayEnumerator) + "." + this.name.asName(
143             byteArrayEnumerator) + "(" + this.parameterCount + ")"
144         is LightUsage.LightFieldUsage -> this.owner.name.asName(byteArrayEnumerator) + "." + this.name.asName(byteArrayEnumerator)
145         is LightUsage.LightClassUsage -> this.name.asName(byteArrayEnumerator)
146         is LightUsage.LightFunExprUsage -> "fun_expr(" + this.name.asName(byteArrayEnumerator) + ")"
147         else -> throw UnsupportedOperationException()
148       }
149
150   private fun Int.asFileName(fileNameEnumerator: PersistentStringEnumerator) = FileUtil.getNameWithoutExtension(File(fileNameEnumerator.valueOf(this)).canonicalFile)
151 }