2 * Copyright 2000-2016 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.jetbrains.references
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
33 abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
34 public override fun setUp() {
36 System.setProperty(BackwardReferenceIndexWriter.PROP_KEY, true.toString())
39 public override fun tearDown() {
41 System.clearProperty(BackwardReferenceIndexWriter.PROP_KEY)
44 protected fun assertIndexOnRebuild(vararg files: String) {
45 var representativeFile: String? = null
47 val addedFile = addFile(file)
48 if (representativeFile == null) {
49 representativeFile = addedFile
52 addModule("m", PathUtil.getParentPath(representativeFile!!))
54 assertIndexEquals("initialIndex.txt")
57 protected fun renameFile(fileToRename: String, newName: String) {
58 rename(orCreateProjectDir.path + "/m/" + fileToRename, newName)
61 protected fun changeFileContent(name: String, changesSourceFile: String) {
62 changeFile("m/" + name, FileUtil.loadFile(File(testDataRootPath + "/" + getTestName(true) + "/" + changesSourceFile), CharsetToolkit.UTF8_CHARSET))
65 protected fun addFile(name: String): String {
66 return createFile("m/" + name, FileUtil.loadFile(File(getTestDataPath() + name), CharsetToolkit.UTF8_CHARSET))
70 protected fun assertIndexEquals(expectedIndexDumpFile: String) {
71 assertSameLinesWithFile(testDataRootPath + "/" + getTestName(true) + "/" + expectedIndexDumpFile, indexAsText())
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)
81 val fileEnumerator = index.filePathEnumerator
82 val nameEnumerator = index.byteSeqEum
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))
94 hierarchyText.add(superClassName + " -> " + inheritorsText.joinToString(separator = " "))
98 result.append(hierarchyText.joinToString(separator = "\n"))
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))
108 referencesText.add(usage.asText(nameEnumerator) + " in " + referents.joinToString(separator = " "))
111 referencesText.sort()
112 result.append(referencesText.joinToString(separator = "\n"))
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))
121 definitionFiles.sort()
122 classDefs.add(usage.asText(nameEnumerator) + " in " + definitionFiles.joinToString(separator = " "))
126 result.append(classDefs.joinToString(separator = "\n"))
128 return result.toString()
134 private fun getTestDataPath() = testDataRootPath + "/" + getTestName(true) + "/"
136 private fun Int.asName(byteArrayEnumerator: ByteArrayEnumerator): String = Convert.utf2string(byteArrayEnumerator.valueOf(this))
138 private fun CompilerBackwardReferenceIndex.LightDefinition.asText(byteArrayEnumerator: ByteArrayEnumerator) = this.usage.asText(byteArrayEnumerator)
140 private fun LightUsage.asText(byteArrayEnumerator: ByteArrayEnumerator): String =
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()
150 private fun Int.asFileName(fileNameEnumerator: PersistentStringEnumerator) = FileUtil.getNameWithoutExtension(File(fileNameEnumerator.valueOf(this)).canonicalFile)