J2K diagnostic tests: prettify
This commit is contained in:
@@ -17,12 +17,9 @@
|
|||||||
package org.jetbrains.kotlin.checkers
|
package org.jetbrains.kotlin.checkers
|
||||||
|
|
||||||
import com.google.common.base.Predicate
|
import com.google.common.base.Predicate
|
||||||
import com.google.common.collect.Sets
|
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import junit.framework.TestCase
|
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.analyzer.common.DefaultAnalyzerFacade
|
import org.jetbrains.kotlin.analyzer.common.DefaultAnalyzerFacade
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
|
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
|
||||||
@@ -31,12 +28,17 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
import org.jetbrains.kotlin.container.getService
|
import org.jetbrains.kotlin.container.get
|
||||||
import org.jetbrains.kotlin.context.*
|
import org.jetbrains.kotlin.context.ModuleContext
|
||||||
|
import org.jetbrains.kotlin.context.SimpleGlobalContext
|
||||||
|
import org.jetbrains.kotlin.context.withModule
|
||||||
|
import org.jetbrains.kotlin.context.withProject
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.diagnostics.*
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
|
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
|
||||||
import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
|
import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
|
||||||
@@ -46,12 +48,10 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.platform.JvmBuiltIns
|
import org.jetbrains.kotlin.platform.JvmBuiltIns
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||||
@@ -63,53 +63,47 @@ import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
|||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.util.DescriptorValidator
|
import org.jetbrains.kotlin.test.util.DescriptorValidator
|
||||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator
|
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator
|
||||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.*
|
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE
|
||||||
import org.jetbrains.kotlin.utils.rethrow
|
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE_ALL
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||||
override fun analyzeAndCheck(testDataFile: File, testFiles: List<BaseDiagnosticsTest.TestFile>) {
|
override fun analyzeAndCheck(testDataFile: File, files: List<TestFile>) {
|
||||||
val groupedByModule = testFiles.groupByTo<TestFile, TestModule, LinkedHashMap<TestModule, List<TestFile>>>(
|
val groupedByModule = files.groupBy(TestFile::module)
|
||||||
LinkedHashMap<TestModule, List<TestFile>>()
|
|
||||||
) { file -> file.module }
|
|
||||||
|
|
||||||
val checkLazyResolveLog = testFiles.any { file -> file.checkLazyLog }
|
|
||||||
|
|
||||||
var lazyOperationsLog: LazyOperationsLog? = null
|
var lazyOperationsLog: LazyOperationsLog? = null
|
||||||
val context: GlobalContext
|
|
||||||
|
|
||||||
val tracker = ExceptionTracker()
|
val tracker = ExceptionTracker()
|
||||||
if (checkLazyResolveLog) {
|
val storageManager: StorageManager
|
||||||
|
if (files.any(TestFile::checkLazyLog)) {
|
||||||
lazyOperationsLog = LazyOperationsLog(HASH_SANITIZER)
|
lazyOperationsLog = LazyOperationsLog(HASH_SANITIZER)
|
||||||
context = SimpleGlobalContext(
|
storageManager = LoggingStorageManager(
|
||||||
LoggingStorageManager(
|
LockBasedStorageManager.createWithExceptionHandling(tracker),
|
||||||
LockBasedStorageManager.createWithExceptionHandling(tracker),
|
lazyOperationsLog.addRecordFunction
|
||||||
lazyOperationsLog.addRecordFunction
|
|
||||||
),
|
|
||||||
tracker
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
context = SimpleGlobalContext(LockBasedStorageManager.createWithExceptionHandling(tracker), tracker)
|
storageManager = LockBasedStorageManager.createWithExceptionHandling(tracker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val context = SimpleGlobalContext(storageManager, tracker)
|
||||||
|
|
||||||
val modules = createModules(groupedByModule, context.storageManager)
|
val modules = createModules(groupedByModule, context.storageManager)
|
||||||
val moduleBindings = java.util.HashMap<TestModule, BindingContext>()
|
val moduleBindings = HashMap<TestModule?, BindingContext>()
|
||||||
|
|
||||||
for ((testModule, testFilesInModule) in groupedByModule) {
|
for ((testModule, testFilesInModule) in groupedByModule) {
|
||||||
|
val ktFiles = getKtFiles(testFilesInModule, true)
|
||||||
|
|
||||||
val jetFiles = getJetFiles(testFilesInModule, true)
|
val oldModule = modules[testModule]!!
|
||||||
|
|
||||||
val oldModule = modules.get(testModule)
|
|
||||||
|
|
||||||
val languageVersionSettings = loadLanguageVersionSettings(testFilesInModule)
|
val languageVersionSettings = loadLanguageVersionSettings(testFilesInModule)
|
||||||
val moduleContext = context.withProject(project).withModule(oldModule)
|
val moduleContext = context.withProject(project).withModule(oldModule)
|
||||||
|
|
||||||
val separateModules = groupedByModule.size == 1 && groupedByModule.keys.iterator().next() == null
|
val separateModules = groupedByModule.size == 1 && groupedByModule.keys.single() == null
|
||||||
val result = analyzeModuleContents(
|
val result = analyzeModuleContents(
|
||||||
moduleContext, jetFiles, CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace(),
|
moduleContext, ktFiles, CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace(),
|
||||||
languageVersionSettings, separateModules
|
languageVersionSettings, separateModules
|
||||||
)
|
)
|
||||||
if (oldModule != result.moduleDescriptor) {
|
if (oldModule != result.moduleDescriptor) {
|
||||||
@@ -117,36 +111,37 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
// (its API does not support working with a module created beforehand).
|
// (its API does not support working with a module created beforehand).
|
||||||
// So, we should replace the old (effectively discarded) module with the new one everywhere in dependencies.
|
// So, we should replace the old (effectively discarded) module with the new one everywhere in dependencies.
|
||||||
// TODO: dirty hack, refactor this test so that it doesn't create ModuleDescriptor instances
|
// TODO: dirty hack, refactor this test so that it doesn't create ModuleDescriptor instances
|
||||||
modules.put(testModule, result.moduleDescriptor)
|
modules[testModule] = result.moduleDescriptor as ModuleDescriptorImpl
|
||||||
for (module in modules.values) {
|
for (module in modules.values) {
|
||||||
val it = module.testOnly_AllDependentModules.listIterator()
|
@Suppress("DEPRECATION")
|
||||||
|
val it = (module.testOnly_AllDependentModules as MutableList).listIterator()
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
if (it.next() == oldModule) {
|
if (it.next() == oldModule) {
|
||||||
it.set(result.moduleDescriptor)
|
it.set(result.moduleDescriptor as ModuleDescriptorImpl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleBindings.put(testModule, result.bindingContext)
|
moduleBindings[testModule] = result.bindingContext
|
||||||
checkAllResolvedCallsAreCompleted(jetFiles, result.bindingContext)
|
checkAllResolvedCallsAreCompleted(ktFiles, result.bindingContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to always create a test data file (txt) if it was missing,
|
// We want to always create a test data file (txt) if it was missing,
|
||||||
// but don't want to skip the following checks in case this one fails
|
// but don't want to skip the following checks in case this one fails
|
||||||
var exceptionFromLazyResolveLogValidation: Throwable? = null
|
var exceptionFromLazyResolveLogValidation: Throwable? = null
|
||||||
if (checkLazyResolveLog) {
|
if (lazyOperationsLog != null) {
|
||||||
exceptionFromLazyResolveLogValidation = checkLazyResolveLog(lazyOperationsLog, testDataFile)
|
exceptionFromLazyResolveLogValidation = checkLazyResolveLog(lazyOperationsLog, testDataFile)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val lazyLogFile = getLazyLogFile(testDataFile)
|
val lazyLogFile = getLazyLogFile(testDataFile)
|
||||||
TestCase.assertFalse("No lazy log expected, but found: " + lazyLogFile.getAbsolutePath(), lazyLogFile.exists())
|
assertFalse("No lazy log expected, but found: ${lazyLogFile.absolutePath}", lazyLogFile.exists())
|
||||||
}
|
}
|
||||||
|
|
||||||
var exceptionFromDescriptorValidation: Throwable? = null
|
var exceptionFromDescriptorValidation: Throwable? = null
|
||||||
try {
|
try {
|
||||||
val expectedFile = File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".txt")
|
val expectedFile = File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".txt")
|
||||||
validateAndCompareDescriptorWithFile(expectedFile, testFiles, modules)
|
validateAndCompareDescriptorWithFile(expectedFile, files, modules)
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
exceptionFromDescriptorValidation = e
|
exceptionFromDescriptorValidation = e
|
||||||
@@ -156,11 +151,11 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
var ok = true
|
var ok = true
|
||||||
|
|
||||||
val actualText = StringBuilder()
|
val actualText = StringBuilder()
|
||||||
for (testFile in testFiles) {
|
for (testFile in files) {
|
||||||
val module = testFile.module
|
val module = testFile.module
|
||||||
val isCommonModule = modules.get(module).getMultiTargetPlatform() === MultiTargetPlatform.Common
|
val isCommonModule = modules[module]!!.getMultiTargetPlatform() == MultiTargetPlatform.Common
|
||||||
ok = ok and testFile.getActualText(
|
ok = ok and testFile.getActualText(
|
||||||
moduleBindings.get(module), actualText,
|
moduleBindings[module]!!, actualText,
|
||||||
shouldSkipJvmSignatureDiagnostics(groupedByModule) || isCommonModule
|
shouldSkipJvmSignatureDiagnostics(groupedByModule) || isCommonModule
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -168,7 +163,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
var exceptionFromDynamicCallDescriptorsValidation: Throwable? = null
|
var exceptionFromDynamicCallDescriptorsValidation: Throwable? = null
|
||||||
try {
|
try {
|
||||||
val expectedFile = File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".dynamic.txt")
|
val expectedFile = File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".dynamic.txt")
|
||||||
checkDynamicCallDescriptors(expectedFile, testFiles)
|
checkDynamicCallDescriptors(expectedFile, files)
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
exceptionFromDynamicCallDescriptorsValidation = e
|
exceptionFromDynamicCallDescriptorsValidation = e
|
||||||
@@ -176,41 +171,34 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
|
|
||||||
KotlinTestUtils.assertEqualsToFile(testDataFile, actualText.toString())
|
KotlinTestUtils.assertEqualsToFile(testDataFile, actualText.toString())
|
||||||
|
|
||||||
TestCase.assertTrue("Diagnostics mismatch. See the output above", ok)
|
assertTrue("Diagnostics mismatch. See the output above", ok)
|
||||||
|
|
||||||
// now we throw a previously found error, if any
|
// now we throw a previously found error, if any
|
||||||
if (exceptionFromDescriptorValidation != null) {
|
exceptionFromDescriptorValidation?.let { throw it }
|
||||||
throw rethrow(exceptionFromDescriptorValidation)
|
exceptionFromLazyResolveLogValidation?.let { throw it }
|
||||||
}
|
exceptionFromDynamicCallDescriptorsValidation?.let { throw it }
|
||||||
if (exceptionFromLazyResolveLogValidation != null) {
|
|
||||||
throw rethrow(exceptionFromLazyResolveLogValidation)
|
|
||||||
}
|
|
||||||
if (exceptionFromDynamicCallDescriptorsValidation != null) {
|
|
||||||
throw rethrow(exceptionFromDynamicCallDescriptorsValidation)
|
|
||||||
}
|
|
||||||
|
|
||||||
performAdditionalChecksAfterDiagnostics(testDataFile, testFiles, groupedByModule, modules, moduleBindings)
|
performAdditionalChecksAfterDiagnostics(testDataFile, files, groupedByModule, modules, moduleBindings)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun performAdditionalChecksAfterDiagnostics(
|
protected open fun performAdditionalChecksAfterDiagnostics(
|
||||||
testDataFile: File,
|
testDataFile: File,
|
||||||
testFiles: List<BaseDiagnosticsTest.TestFile>,
|
testFiles: List<TestFile>,
|
||||||
moduleFiles: Map<BaseDiagnosticsTest.TestModule, List<BaseDiagnosticsTest.TestFile>>,
|
moduleFiles: Map<TestModule?, List<TestFile>>,
|
||||||
moduleDescriptors: Map<BaseDiagnosticsTest.TestModule, ModuleDescriptorImpl>,
|
moduleDescriptors: Map<TestModule?, ModuleDescriptorImpl>,
|
||||||
moduleBindings: Map<BaseDiagnosticsTest.TestModule, BindingContext>
|
moduleBindings: Map<TestModule?, BindingContext>
|
||||||
) {
|
) {
|
||||||
// To be overridden by diagnostic-like tests.
|
// To be overridden by diagnostic-like tests.
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadLanguageVersionSettings(module: List<BaseDiagnosticsTest.TestFile>): LanguageVersionSettings? {
|
private fun loadLanguageVersionSettings(module: List<TestFile>): LanguageVersionSettings? {
|
||||||
var result: LanguageVersionSettings? = null
|
var result: LanguageVersionSettings? = null
|
||||||
for (file in module) {
|
for (file in module) {
|
||||||
val current = file.customLanguageVersionSettings
|
val current = file.customLanguageVersionSettings
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
if (result != null && result != current) {
|
if (result != null && result != current) {
|
||||||
Assert.fail(
|
Assert.fail(
|
||||||
"More than one file in the module has " + BaseDiagnosticsTest.LANGUAGE_DIRECTIVE + " or " +
|
"More than one file in the module has $LANGUAGE_DIRECTIVE or $API_VERSION_DIRECTIVE directive specified. " +
|
||||||
BaseDiagnosticsTest.API_VERSION_DIRECTIVE + " directive specified. " +
|
|
||||||
"This is not supported. Please move all directives into one file"
|
"This is not supported. Please move all directives into one file"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -221,59 +209,49 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkDynamicCallDescriptors(expectedFile: File, testFiles: List<BaseDiagnosticsTest.TestFile>) {
|
private fun checkDynamicCallDescriptors(expectedFile: File, testFiles: List<TestFile>) {
|
||||||
val serializer = RecursiveDescriptorComparator(RECURSIVE_ALL)
|
val serializer = RecursiveDescriptorComparator(RECURSIVE_ALL)
|
||||||
|
|
||||||
val actualText = StringBuilder()
|
val actualText = StringBuilder()
|
||||||
|
|
||||||
for (testFile in testFiles) {
|
for (testFile in testFiles) {
|
||||||
val dynamicCallDescriptors = testFile.dynamicCallDescriptors
|
for (descriptor in testFile.dynamicCallDescriptors) {
|
||||||
|
|
||||||
for (descriptor in dynamicCallDescriptors) {
|
|
||||||
val actualSerialized = serializer.serializeRecursively(descriptor)
|
val actualSerialized = serializer.serializeRecursively(descriptor)
|
||||||
actualText.append(actualSerialized)
|
actualText.append(actualSerialized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actualText.length != 0 || expectedFile.exists()) {
|
if (actualText.isNotEmpty() || expectedFile.exists()) {
|
||||||
KotlinTestUtils.assertEqualsToFile(expectedFile, actualText.toString())
|
KotlinTestUtils.assertEqualsToFile(expectedFile, actualText.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shouldSkipJvmSignatureDiagnostics(groupedByModule: Map<BaseDiagnosticsTest.TestModule, List<BaseDiagnosticsTest.TestFile>>): Boolean {
|
protected open fun shouldSkipJvmSignatureDiagnostics(groupedByModule: Map<TestModule?, List<TestFile>>): Boolean =
|
||||||
return groupedByModule.size > 1
|
groupedByModule.size > 1
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkLazyResolveLog(lazyOperationsLog: LazyOperationsLog, testDataFile: File): Throwable? {
|
private fun checkLazyResolveLog(lazyOperationsLog: LazyOperationsLog, testDataFile: File): Throwable? =
|
||||||
var exceptionFromLazyResolveLogValidation: Throwable? = null
|
try {
|
||||||
try {
|
val expectedFile = getLazyLogFile(testDataFile)
|
||||||
val expectedFile = getLazyLogFile(testDataFile)
|
KotlinTestUtils.assertEqualsToFile(expectedFile, lazyOperationsLog.getText(), HASH_SANITIZER)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
e
|
||||||
|
}
|
||||||
|
|
||||||
KotlinTestUtils.assertEqualsToFile(
|
private fun getLazyLogFile(testDataFile: File): File =
|
||||||
expectedFile,
|
File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".lazy.log")
|
||||||
lazyOperationsLog.getText(),
|
|
||||||
HASH_SANITIZER
|
|
||||||
)
|
|
||||||
}
|
|
||||||
catch (e: Throwable) {
|
|
||||||
exceptionFromLazyResolveLogValidation = e
|
|
||||||
}
|
|
||||||
|
|
||||||
return exceptionFromLazyResolveLogValidation
|
protected open fun analyzeModuleContents(
|
||||||
}
|
|
||||||
|
|
||||||
private fun getLazyLogFile(testDataFile: File): File {
|
|
||||||
return File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".lazy.log")
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun analyzeModuleContents(
|
|
||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
files: List<KtFile>,
|
files: List<KtFile>,
|
||||||
moduleTrace: BindingTrace,
|
moduleTrace: BindingTrace,
|
||||||
languageVersionSettings: LanguageVersionSettings?,
|
languageVersionSettings: LanguageVersionSettings?,
|
||||||
separateModules: Boolean
|
separateModules: Boolean
|
||||||
): AnalysisResult {
|
): AnalysisResult {
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
var files = files
|
var files = files
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
var languageVersionSettings = languageVersionSettings
|
var languageVersionSettings = languageVersionSettings
|
||||||
val configuration: CompilerConfiguration
|
val configuration: CompilerConfiguration
|
||||||
if (languageVersionSettings != null) {
|
if (languageVersionSettings != null) {
|
||||||
@@ -305,22 +283,21 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
val moduleDescriptor = moduleContext.module as ModuleDescriptorImpl
|
val moduleDescriptor = moduleContext.module as ModuleDescriptorImpl
|
||||||
|
|
||||||
val platform = moduleDescriptor.getMultiTargetPlatform()
|
val platform = moduleDescriptor.getMultiTargetPlatform()
|
||||||
if (platform === MultiTargetPlatform.Common) {
|
if (platform == MultiTargetPlatform.Common) {
|
||||||
|
|
||||||
return DefaultAnalyzerFacade.analyzeFiles(
|
return DefaultAnalyzerFacade.analyzeFiles(
|
||||||
files, moduleDescriptor.name, true,
|
files, moduleDescriptor.name, true,
|
||||||
mapOf<ModuleDescriptor.Capability<out Any>, Any>(
|
mapOf(
|
||||||
MultiTargetPlatform.CAPABILITY.to<ModuleDescriptor.Capability<MultiTargetPlatform>, MultiTargetPlatform.Common>(MultiTargetPlatform.Common),
|
MultiTargetPlatform.CAPABILITY to MultiTargetPlatform.Common,
|
||||||
MODULE_FILES.to<ModuleDescriptor.Capability<List<KtFile>>, List<KtFile>>(files)
|
MODULE_FILES to files
|
||||||
)
|
)
|
||||||
) { info, content ->
|
) { _, _ ->
|
||||||
// TODO
|
// TODO
|
||||||
PackagePartProvider.Empty
|
PackagePartProvider.Empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (platform != null) {
|
else if (platform != null) {
|
||||||
// TODO: analyze with the correct platform, not always JVM
|
// TODO: analyze with the correct platform, not always JVM
|
||||||
files = files.plus<KtFile>(getCommonCodeFilesForPlatformSpecificModule(moduleDescriptor))
|
files += getCommonCodeFilesForPlatformSpecificModule(moduleDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val moduleContentScope = GlobalSearchScope.allScope(moduleContext.project)
|
val moduleContentScope = GlobalSearchScope.allScope(moduleContext.project)
|
||||||
@@ -336,16 +313,14 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
moduleClassResolver
|
moduleClassResolver
|
||||||
)
|
)
|
||||||
container.initJvmBuiltInsForTopDownAnalysis(moduleDescriptor, languageVersionSettings)
|
container.initJvmBuiltInsForTopDownAnalysis(moduleDescriptor, languageVersionSettings)
|
||||||
moduleClassResolver.resolver = container.getService(JavaDescriptorResolver::class.java)
|
moduleClassResolver.resolver = container.get<JavaDescriptorResolver>()
|
||||||
|
|
||||||
moduleDescriptor.initialize(CompositePackageFragmentProvider(Arrays.asList<PackageFragmentProvider>(
|
moduleDescriptor.initialize(CompositePackageFragmentProvider(listOf(
|
||||||
container.getService(KotlinCodeAnalyzer::class.java).getPackageFragmentProvider(),
|
container.get<KotlinCodeAnalyzer>().packageFragmentProvider,
|
||||||
container.getService(JavaDescriptorResolver::class.java).packageFragmentProvider
|
container.get<JavaDescriptorResolver>().packageFragmentProvider
|
||||||
)))
|
)))
|
||||||
|
|
||||||
container.getService(LazyTopDownAnalyzer::class.java).analyzeDeclarations(
|
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||||
TopDownAnalysisMode.TopLevelDeclarations, files, DataFlowInfo.EMPTY
|
|
||||||
)
|
|
||||||
|
|
||||||
return AnalysisResult.success(moduleTrace.bindingContext, moduleDescriptor)
|
return AnalysisResult.success(moduleTrace.bindingContext, moduleDescriptor)
|
||||||
}
|
}
|
||||||
@@ -353,14 +328,16 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
private fun getCommonCodeFilesForPlatformSpecificModule(moduleDescriptor: ModuleDescriptorImpl): List<KtFile> {
|
private fun getCommonCodeFilesForPlatformSpecificModule(moduleDescriptor: ModuleDescriptorImpl): List<KtFile> {
|
||||||
// We assume that a platform-specific module _implements_ all declarations from common modules which are immediate dependencies.
|
// We assume that a platform-specific module _implements_ all declarations from common modules which are immediate dependencies.
|
||||||
// So we collect all sources from such modules to analyze in the platform-specific module as well
|
// So we collect all sources from such modules to analyze in the platform-specific module as well
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
val dependencies = moduleDescriptor.testOnly_AllDependentModules
|
val dependencies = moduleDescriptor.testOnly_AllDependentModules
|
||||||
|
|
||||||
// TODO: diagnostics on common code reported during the platform module analysis should be distinguished somehow
|
// TODO: diagnostics on common code reported during the platform module analysis should be distinguished somehow
|
||||||
// E.g. "<!JVM:IMPLEMENTATION_WITHOUT_HEADER!>...<!>
|
// E.g. "<!JVM:IMPLEMENTATION_WITHOUT_HEADER!>...<!>
|
||||||
val result = ArrayList<KtFile>(0)
|
val result = ArrayList<KtFile>(0)
|
||||||
for (dependency in dependencies) {
|
for (dependency in dependencies) {
|
||||||
if (dependency.getCapability(MultiTargetPlatform.CAPABILITY) === MultiTargetPlatform.Common) {
|
if (dependency.getCapability(MultiTargetPlatform.CAPABILITY) == MultiTargetPlatform.Common) {
|
||||||
val files = dependency.getCapability(MODULE_FILES) ?: error("MODULE_FILES should have been set for the common module: " + dependency)
|
val files = dependency.getCapability(MODULE_FILES)
|
||||||
|
?: error("MODULE_FILES should have been set for the common module: $dependency")
|
||||||
result.addAll(files)
|
result.addAll(files)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,11 +347,11 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
|
|
||||||
private fun validateAndCompareDescriptorWithFile(
|
private fun validateAndCompareDescriptorWithFile(
|
||||||
expectedFile: File,
|
expectedFile: File,
|
||||||
testFiles: List<BaseDiagnosticsTest.TestFile>,
|
testFiles: List<TestFile>,
|
||||||
modules: Map<BaseDiagnosticsTest.TestModule, ModuleDescriptorImpl>
|
modules: Map<TestModule?, ModuleDescriptorImpl>
|
||||||
) {
|
) {
|
||||||
if (testFiles.any { file -> InTextDirectivesUtils.isDirectiveDefined(file.expectedText, "// SKIP_TXT") }) {
|
if (testFiles.any { file -> InTextDirectivesUtils.isDirectiveDefined(file.expectedText, "// SKIP_TXT") }) {
|
||||||
TestCase.assertFalse(".txt file should not exist if SKIP_TXT directive is used: " + expectedFile, expectedFile.exists())
|
assertFalse(".txt file should not exist if SKIP_TXT directive is used: $expectedFile", expectedFile.exists())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,14 +360,24 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
val isMultiModuleTest = modules.size != 1
|
val isMultiModuleTest = modules.size != 1
|
||||||
val rootPackageText = StringBuilder()
|
val rootPackageText = StringBuilder()
|
||||||
|
|
||||||
val module = modules.keys.sorted().iterator()
|
val sortedModules = modules.keys.sortedWith(Comparator { x, y ->
|
||||||
|
when {
|
||||||
|
x == null && y == null -> 0
|
||||||
|
x == null && y != null -> -1
|
||||||
|
x != null && y == null -> 1
|
||||||
|
x != null && y != null -> x.compareTo(y)
|
||||||
|
else -> error("Unreachable")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
val module = sortedModules.iterator()
|
||||||
while (module.hasNext()) {
|
while (module.hasNext()) {
|
||||||
val moduleDescriptor = modules[module.next()]
|
val moduleDescriptor = modules[module.next()]!!
|
||||||
val aPackage = moduleDescriptor.getPackage(FqName.ROOT)
|
val aPackage = moduleDescriptor.getPackage(FqName.ROOT)
|
||||||
TestCase.assertFalse(aPackage.isEmpty())
|
assertFalse(aPackage.isEmpty())
|
||||||
|
|
||||||
if (isMultiModuleTest) {
|
if (isMultiModuleTest) {
|
||||||
rootPackageText.append(String.format("// -- Module: %s --\n", moduleDescriptor.getName()))
|
rootPackageText.append(String.format("// -- Module: %s --\n", moduleDescriptor.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
val actualSerialized = comparator.serializeRecursively(aPackage)
|
val actualSerialized = comparator.serializeRecursively(aPackage)
|
||||||
@@ -403,7 +390,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
|
|
||||||
val lineCount = StringUtil.getLineBreakCount(rootPackageText)
|
val lineCount = StringUtil.getLineBreakCount(rootPackageText)
|
||||||
assert(lineCount < 1000) {
|
assert(lineCount < 1000) {
|
||||||
"Rendered descriptors of this test take up " + lineCount + " lines. " +
|
"Rendered descriptors of this test take up $lineCount lines. " +
|
||||||
"Please ensure you don't render JRE contents to the .txt file. " +
|
"Please ensure you don't render JRE contents to the .txt file. " +
|
||||||
"Such tests are hard to maintain, take long time to execute and are subject to sudden unreviewed changes anyway."
|
"Such tests are hard to maintain, take long time to execute and are subject to sudden unreviewed changes anyway."
|
||||||
}
|
}
|
||||||
@@ -411,20 +398,19 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
KotlinTestUtils.assertEqualsToFile(expectedFile, rootPackageText.toString())
|
KotlinTestUtils.assertEqualsToFile(expectedFile, rootPackageText.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createdAffectedPackagesConfiguration(testFiles: List<BaseDiagnosticsTest.TestFile>, modules: Collection<ModuleDescriptor>): RecursiveDescriptorComparator.Configuration {
|
private fun createdAffectedPackagesConfiguration(
|
||||||
val packagesNames = getTopLevelPackagesFromFileList(getJetFiles(testFiles, false))
|
testFiles: List<TestFile>,
|
||||||
|
modules: Collection<ModuleDescriptor>
|
||||||
|
): RecursiveDescriptorComparator.Configuration {
|
||||||
|
val packagesNames = getTopLevelPackagesFromFileList(getKtFiles(testFiles, false))
|
||||||
|
|
||||||
val stepIntoFilter = Predicate<DeclarationDescriptor> { descriptor ->
|
val stepIntoFilter = Predicate<DeclarationDescriptor> { descriptor ->
|
||||||
val module = DescriptorUtils.getContainingModuleOrNull(descriptor!!)
|
val module = DescriptorUtils.getContainingModuleOrNull(descriptor!!)
|
||||||
if (!modules.contains(module)) return@Predicate false
|
if (module !in modules) return@Predicate false
|
||||||
|
|
||||||
if (descriptor is PackageViewDescriptor) {
|
if (descriptor is PackageViewDescriptor) {
|
||||||
val fqName = descriptor.fqName
|
val fqName = descriptor.fqName
|
||||||
|
return@Predicate fqName.isRoot || fqName.pathSegments().first() in packagesNames
|
||||||
if (fqName.isRoot) return@Predicate true
|
|
||||||
|
|
||||||
val firstName = fqName.pathSegments()[0]
|
|
||||||
return@Predicate packagesNames.contains(firstName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
@@ -433,21 +419,16 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
return RECURSIVE.filterRecursion(stepIntoFilter).withValidationStrategy(DescriptorValidator.ValidationVisitor.errorTypesAllowed())
|
return RECURSIVE.filterRecursion(stepIntoFilter).withValidationStrategy(DescriptorValidator.ValidationVisitor.errorTypesAllowed())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTopLevelPackagesFromFileList(files: List<KtFile>): Set<Name> {
|
private fun getTopLevelPackagesFromFileList(files: List<KtFile>): Set<Name> =
|
||||||
val shortNames = LinkedHashSet<Name>()
|
files.mapTo(LinkedHashSet<Name>()) { file ->
|
||||||
for (file in files) {
|
file.packageFqName.pathSegments().firstOrNull() ?: SpecialNames.ROOT_PACKAGE
|
||||||
val packageFqNameSegments = file.packageFqName.pathSegments()
|
}
|
||||||
val name = if (packageFqNameSegments.isEmpty()) SpecialNames.ROOT_PACKAGE else packageFqNameSegments[0]
|
|
||||||
shortNames.add(name)
|
|
||||||
}
|
|
||||||
return shortNames
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createModules(
|
private fun createModules(
|
||||||
groupedByModule: Map<BaseDiagnosticsTest.TestModule, List<BaseDiagnosticsTest.TestFile>>,
|
groupedByModule: Map<TestModule?, List<TestFile>>,
|
||||||
storageManager: StorageManager
|
storageManager: StorageManager
|
||||||
): Map<BaseDiagnosticsTest.TestModule, ModuleDescriptorImpl> {
|
): MutableMap<TestModule?, ModuleDescriptorImpl> {
|
||||||
val modules = HashMap<BaseDiagnosticsTest.TestModule, ModuleDescriptorImpl>()
|
val modules = HashMap<TestModule?, ModuleDescriptorImpl>()
|
||||||
|
|
||||||
for (testModule in groupedByModule.keys) {
|
for (testModule in groupedByModule.keys) {
|
||||||
val module = if (testModule == null)
|
val module = if (testModule == null)
|
||||||
@@ -461,11 +442,11 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
for (testModule in groupedByModule.keys) {
|
for (testModule in groupedByModule.keys) {
|
||||||
if (testModule == null) continue
|
if (testModule == null) continue
|
||||||
|
|
||||||
val module = modules[testModule]
|
val module = modules[testModule]!!
|
||||||
val dependencies = ArrayList<ModuleDescriptorImpl>()
|
val dependencies = ArrayList<ModuleDescriptorImpl>()
|
||||||
dependencies.add(module)
|
dependencies.add(module)
|
||||||
for (dependency in testModule.getDependencies()) {
|
for (dependency in testModule.getDependencies()) {
|
||||||
dependencies.add(modules[dependency])
|
dependencies.add(modules[dependency]!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies.add(module.builtIns.builtInsModule)
|
dependencies.add(module.builtIns.builtInsModule)
|
||||||
@@ -476,98 +457,76 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
return modules
|
return modules
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun getAdditionalDependencies(module: ModuleDescriptorImpl): List<ModuleDescriptorImpl> {
|
protected open fun getAdditionalDependencies(module: ModuleDescriptorImpl): List<ModuleDescriptorImpl> =
|
||||||
return emptyList()
|
emptyList()
|
||||||
}
|
|
||||||
|
|
||||||
protected fun createModule(moduleName: String, storageManager: StorageManager): ModuleDescriptorImpl {
|
protected open fun createModule(moduleName: String, storageManager: StorageManager): ModuleDescriptorImpl {
|
||||||
val nameSuffix = moduleName.substringAfterLast("-", "")
|
val nameSuffix = moduleName.substringAfterLast("-", "")
|
||||||
val platform = if (nameSuffix.isEmpty())
|
val platform =
|
||||||
null
|
if (nameSuffix.isEmpty()) null
|
||||||
else if (nameSuffix == "common") MultiTargetPlatform.Common else MultiTargetPlatform.Specific(nameSuffix)
|
else if (nameSuffix == "common") MultiTargetPlatform.Common else MultiTargetPlatform.Specific(nameSuffix)
|
||||||
val capabilities = if (platform == null)
|
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> =
|
||||||
emptyMap<Any, Any>()
|
if (platform == null) emptyMap()
|
||||||
else
|
else mapOf(MultiTargetPlatform.CAPABILITY to platform)
|
||||||
Collections.singletonMap<ModuleDescriptor.Capability<MultiTargetPlatform>, MultiTargetPlatform>(MultiTargetPlatform.CAPABILITY, platform)
|
|
||||||
return ModuleDescriptorImpl(
|
return ModuleDescriptorImpl(
|
||||||
Name.special("<$moduleName>"), storageManager, JvmBuiltIns(storageManager),
|
Name.special("<$moduleName>"), storageManager, JvmBuiltIns(storageManager),
|
||||||
if (platform === MultiTargetPlatform.Common) PlatformKind.DEFAULT else PlatformKind.JVM,
|
if (platform == MultiTargetPlatform.Common) PlatformKind.DEFAULT else PlatformKind.JVM,
|
||||||
SourceKind.TEST, capabilities
|
SourceKind.TEST, capabilities
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun createSealedModule(storageManager: StorageManager): ModuleDescriptorImpl {
|
protected open fun createSealedModule(storageManager: StorageManager): ModuleDescriptorImpl =
|
||||||
val moduleDescriptor = createModule("test-module", storageManager)
|
createModule("test-module", storageManager).apply {
|
||||||
moduleDescriptor.setDependencies(moduleDescriptor, moduleDescriptor.builtIns.builtInsModule)
|
setDependencies(this, builtIns.builtInsModule)
|
||||||
return moduleDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkAllResolvedCallsAreCompleted(jetFiles: List<KtFile>, bindingContext: BindingContext) {
|
|
||||||
for (file in jetFiles) {
|
|
||||||
if (!AnalyzingUtils.getSyntaxErrorRanges(file).isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private fun checkAllResolvedCallsAreCompleted(ktFiles: List<KtFile>, bindingContext: BindingContext) {
|
||||||
|
if (ktFiles.any { file -> AnalyzingUtils.getSyntaxErrorRanges(file).isNotEmpty() }) return
|
||||||
|
|
||||||
val resolvedCallsEntries = bindingContext.getSliceContents(BindingContext.RESOLVED_CALL)
|
val resolvedCallsEntries = bindingContext.getSliceContents(BindingContext.RESOLVED_CALL)
|
||||||
for (entry in resolvedCallsEntries.entries) {
|
for ((call, resolvedCall) in resolvedCallsEntries) {
|
||||||
val element = entry.key.callElement
|
val element = call.callElement
|
||||||
val resolvedCall = entry.value
|
|
||||||
|
|
||||||
val lineAndColumn = DiagnosticUtils.getLineAndColumnInPsiFile(element.containingFile, element.textRange)
|
val lineAndColumn = DiagnosticUtils.getLineAndColumnInPsiFile(element.containingFile, element.textRange)
|
||||||
|
|
||||||
TestCase.assertTrue("Resolved call for '" + element.text + "'" + lineAndColumn + " is not completed",
|
assertTrue("Resolved call for '${element.text}'$lineAndColumn is not completed",
|
||||||
(resolvedCall as MutableResolvedCall<*>).isCompleted)
|
(resolvedCall as MutableResolvedCall<*>).isCompleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkResolvedCallsInDiagnostics(bindingContext)
|
checkResolvedCallsInDiagnostics(bindingContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkResolvedCallsInDiagnostics(bindingContext: BindingContext) {
|
private fun checkResolvedCallsInDiagnostics(bindingContext: BindingContext) {
|
||||||
val diagnosticsStoringResolvedCalls1 = Sets.newHashSet<DiagnosticFactory1<PsiElement, Collection<ResolvedCall<*>>>>(
|
val diagnosticsStoringResolvedCalls1 = setOf(
|
||||||
OVERLOAD_RESOLUTION_AMBIGUITY, NONE_APPLICABLE, CANNOT_COMPLETE_RESOLVE, UNRESOLVED_REFERENCE_WRONG_RECEIVER,
|
OVERLOAD_RESOLUTION_AMBIGUITY, NONE_APPLICABLE, CANNOT_COMPLETE_RESOLVE, UNRESOLVED_REFERENCE_WRONG_RECEIVER,
|
||||||
ASSIGN_OPERATOR_AMBIGUITY, ITERATOR_AMBIGUITY)
|
ASSIGN_OPERATOR_AMBIGUITY, ITERATOR_AMBIGUITY
|
||||||
val diagnosticsStoringResolvedCalls2 = Sets.newHashSet<DiagnosticFactory2<KtExpression, out Comparable<out Comparable<*>>, Collection<ResolvedCall<*>>>>(
|
)
|
||||||
COMPONENT_FUNCTION_AMBIGUITY, DELEGATE_SPECIAL_FUNCTION_AMBIGUITY, DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE)
|
val diagnosticsStoringResolvedCalls2 = setOf(
|
||||||
val diagnostics = bindingContext.diagnostics
|
COMPONENT_FUNCTION_AMBIGUITY, DELEGATE_SPECIAL_FUNCTION_AMBIGUITY, DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE
|
||||||
for (diagnostic in diagnostics) {
|
)
|
||||||
val factory = diagnostic.factory
|
|
||||||
|
|
||||||
if (diagnosticsStoringResolvedCalls1.contains(factory)) {
|
for (diagnostic in bindingContext.diagnostics) {
|
||||||
assertResolvedCallsAreCompleted(
|
when (diagnostic.factory) {
|
||||||
diagnostic, DiagnosticFactory.cast(diagnostic, diagnosticsStoringResolvedCalls1).a)
|
in diagnosticsStoringResolvedCalls1 -> assertResolvedCallsAreCompleted(
|
||||||
}
|
diagnostic, DiagnosticFactory.cast(diagnostic, diagnosticsStoringResolvedCalls1).a
|
||||||
|
)
|
||||||
if (diagnosticsStoringResolvedCalls2.contains(factory)) {
|
in diagnosticsStoringResolvedCalls2 -> assertResolvedCallsAreCompleted(
|
||||||
assertResolvedCallsAreCompleted(
|
diagnostic, DiagnosticFactory.cast(diagnostic, diagnosticsStoringResolvedCalls2).b
|
||||||
diagnostic,
|
)
|
||||||
DiagnosticFactory.cast<DiagnosticWithParameters2<KtExpression, out Comparable<out Comparable<*>>, Collection<ResolvedCall<*>>>>(diagnostic, diagnosticsStoringResolvedCalls2).b)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertResolvedCallsAreCompleted(
|
private fun assertResolvedCallsAreCompleted(diagnostic: Diagnostic, resolvedCalls: Collection<ResolvedCall<*>>) {
|
||||||
diagnostic: Diagnostic, resolvedCalls: Collection<ResolvedCall<*>>
|
|
||||||
) {
|
|
||||||
var allCallsAreCompleted = true
|
|
||||||
for (resolvedCall in resolvedCalls) {
|
|
||||||
if (!(resolvedCall as MutableResolvedCall<*>).isCompleted) {
|
|
||||||
allCallsAreCompleted = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val element = diagnostic.psiElement
|
val element = diagnostic.psiElement
|
||||||
val lineAndColumn = DiagnosticUtils.getLineAndColumnInPsiFile(element.containingFile, element.textRange)
|
val lineAndColumn = DiagnosticUtils.getLineAndColumnInPsiFile(element.containingFile, element.textRange)
|
||||||
|
|
||||||
TestCase.assertTrue("Resolved calls stored in " + diagnostic.factory.name + "\n" +
|
assertTrue("Resolved calls stored in ${diagnostic.factory.name}\nfor '${element.text}'$lineAndColumn are not completed",
|
||||||
"for '" + element.text + "'" + lineAndColumn + " are not completed",
|
resolvedCalls.all { (it as MutableResolvedCall<*>).isCompleted })
|
||||||
allCallsAreCompleted)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val HASH_SANITIZER = fun(s: String): String {
|
private val HASH_SANITIZER = fun(s: String): String = s.replace("@(\\d)+".toRegex(), "")
|
||||||
return s.replace("@(\\d)+".toRegex(), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val MODULE_FILES = ModuleDescriptor.Capability<List<KtFile>>("")
|
private val MODULE_FILES = ModuleDescriptor.Capability<List<KtFile>>("")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,20 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.checkers
|
package org.jetbrains.kotlin.checkers
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet
|
|
||||||
import com.google.common.collect.Lists
|
|
||||||
import com.intellij.lang.java.JavaLanguage
|
import com.intellij.lang.java.JavaLanguage
|
||||||
import com.intellij.openapi.util.Condition
|
import com.intellij.openapi.util.Condition
|
||||||
import com.intellij.openapi.util.Conditions
|
import com.intellij.openapi.util.Conditions
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import com.intellij.psi.PsiFileFactory
|
import com.intellij.psi.PsiFileFactory
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.Function
|
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import com.intellij.util.containers.HashMap
|
import org.jetbrains.kotlin.asJava.getJvmSignatureDiagnostics
|
||||||
import org.jetbrains.kotlin.asJava.*
|
import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestFile
|
||||||
|
import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestModule
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.*
|
import org.jetbrains.kotlin.diagnostics.*
|
||||||
@@ -37,106 +34,84 @@ import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer
|
|||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.utils.*
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Matcher
|
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnosticsTest.TestModule, BaseDiagnosticsTest.TestFile>() {
|
abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, TestFile>() {
|
||||||
|
override fun createTestModule(name: String): TestModule =
|
||||||
|
TestModule(name)
|
||||||
|
|
||||||
override fun createTestModule(name: String): TestModule {
|
override fun createTestFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String>): TestFile =
|
||||||
return TestModule(name)
|
TestFile(module, fileName, text, directives)
|
||||||
}
|
|
||||||
|
|
||||||
override fun createTestFile(module: TestModule, fileName: String, text: String, directives: Map<String, String>): TestFile {
|
override fun doMultiFileTest(
|
||||||
return TestFile(module, fileName, text, directives)
|
file: File,
|
||||||
}
|
modules: @JvmSuppressWildcards Map<String, ModuleAndDependencies>,
|
||||||
|
testFiles: List<TestFile>
|
||||||
override fun doMultiFileTest(file: File, modules: Map<String, KotlinMultiFileTestWithJava<BaseDiagnosticsTest.TestFile, BaseDiagnosticsTest.TestModule>.ModuleAndDependencies>, testFiles: List<TestFile>) {
|
) {
|
||||||
for (moduleAndDependencies in modules.values) {
|
for (moduleAndDependencies in modules.values) {
|
||||||
val dependencies = moduleAndDependencies.dependencies.map(
|
moduleAndDependencies.module.getDependencies().addAll(moduleAndDependencies.dependencies.map { name ->
|
||||||
{ name ->
|
modules[name]?.module ?: error("Dependency not found: $name for module ${moduleAndDependencies.module.name}")
|
||||||
val dependency = modules[name] ?: error("Dependency not found: " +
|
})
|
||||||
name +
|
|
||||||
" for module " +
|
|
||||||
moduleAndDependencies.module.name)
|
|
||||||
dependency.module
|
|
||||||
}
|
|
||||||
)
|
|
||||||
moduleAndDependencies.module.getDependencies().addAll(dependencies)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
analyzeAndCheck(file, testFiles)
|
analyzeAndCheck(file, testFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun analyzeAndCheck(
|
protected abstract fun analyzeAndCheck(testDataFile: File, files: List<TestFile>)
|
||||||
testDataFile: File,
|
|
||||||
files: List<TestFile>
|
|
||||||
)
|
|
||||||
|
|
||||||
protected fun getJetFiles(testFiles: List<TestFile>, includeExtras: Boolean): List<KtFile> {
|
protected fun getKtFiles(testFiles: List<TestFile>, includeExtras: Boolean): List<KtFile> {
|
||||||
var declareFlexibleType = false
|
var declareFlexibleType = false
|
||||||
var declareCheckType = false
|
var declareCheckType = false
|
||||||
val jetFiles = Lists.newArrayList<KtFile>()
|
val ktFiles = arrayListOf<KtFile>()
|
||||||
for (testFile in testFiles) {
|
for (testFile in testFiles) {
|
||||||
if (testFile.jetFile != null) {
|
ktFiles.addIfNotNull(testFile.ktFile)
|
||||||
jetFiles.add(testFile.jetFile)
|
|
||||||
}
|
|
||||||
declareFlexibleType = declareFlexibleType or testFile.declareFlexibleType
|
declareFlexibleType = declareFlexibleType or testFile.declareFlexibleType
|
||||||
declareCheckType = declareCheckType or testFile.declareCheckType
|
declareCheckType = declareCheckType or testFile.declareCheckType
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeExtras) {
|
if (includeExtras) {
|
||||||
if (declareFlexibleType) {
|
if (declareFlexibleType) {
|
||||||
jetFiles.add(KotlinTestUtils.createFile("EXPLICIT_FLEXIBLE_TYPES.kt", EXPLICIT_FLEXIBLE_TYPES_DECLARATIONS, project))
|
ktFiles.add(KotlinTestUtils.createFile("EXPLICIT_FLEXIBLE_TYPES.kt", EXPLICIT_FLEXIBLE_TYPES_DECLARATIONS, project))
|
||||||
}
|
}
|
||||||
if (declareCheckType) {
|
if (declareCheckType) {
|
||||||
jetFiles.add(KotlinTestUtils.createFile("CHECK_TYPE.kt", CHECK_TYPE_DECLARATIONS, project))
|
ktFiles.add(KotlinTestUtils.createFile("CHECK_TYPE.kt", CHECK_TYPE_DECLARATIONS, project))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return jetFiles
|
return ktFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestModule(val name: String) : Comparable<TestModule> {
|
class TestModule(val name: String) : Comparable<TestModule> {
|
||||||
private val dependencies = ArrayList<TestModule>()
|
private val dependencies = ArrayList<TestModule>()
|
||||||
|
|
||||||
fun getDependencies(): MutableList<TestModule> {
|
fun getDependencies(): MutableList<TestModule> = dependencies
|
||||||
return dependencies
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun compareTo(module: TestModule): Int {
|
override fun compareTo(other: TestModule): Int = name.compareTo(other.name)
|
||||||
return name.compareTo(module.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String = name
|
||||||
return name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DiagnosticTestLanguageVersionSettings(
|
class DiagnosticTestLanguageVersionSettings(
|
||||||
private val languageFeatures: Map<LanguageFeature, Boolean>, override val apiVersion: ApiVersion
|
private val languageFeatures: Map<LanguageFeature, Boolean>,
|
||||||
|
override val apiVersion: ApiVersion
|
||||||
) : LanguageVersionSettings {
|
) : LanguageVersionSettings {
|
||||||
|
override fun supportsFeature(feature: LanguageFeature): Boolean =
|
||||||
|
languageFeatures[feature] ?: LanguageVersionSettingsImpl.DEFAULT.supportsFeature(feature)
|
||||||
|
|
||||||
override fun supportsFeature(feature: LanguageFeature): Boolean {
|
// TODO provide base language version
|
||||||
val enabled = languageFeatures[feature]
|
override val languageVersion: LanguageVersion
|
||||||
return enabled ?: LanguageVersionSettingsImpl.DEFAULT.supportsFeature(feature)
|
|
||||||
}
|
|
||||||
|
|
||||||
override // TODO provide base language version
|
|
||||||
val languageVersion: LanguageVersion
|
|
||||||
get() = throw UnsupportedOperationException("This instance of LanguageVersionSettings should be used for tests only")
|
get() = throw UnsupportedOperationException("This instance of LanguageVersionSettings should be used for tests only")
|
||||||
|
|
||||||
override fun equals(obj: Any?): Boolean {
|
override fun equals(other: Any?): Boolean =
|
||||||
return obj is DiagnosticTestLanguageVersionSettings &&
|
other is DiagnosticTestLanguageVersionSettings && other.languageFeatures == languageFeatures && other.apiVersion == apiVersion
|
||||||
obj.languageFeatures == languageFeatures &&
|
|
||||||
obj.apiVersion == apiVersion
|
override fun hashCode(): Int =
|
||||||
}
|
31 * languageFeatures.hashCode() + apiVersion.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class TestFile(
|
inner class TestFile(
|
||||||
@@ -145,14 +120,14 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
textWithMarkers: String,
|
textWithMarkers: String,
|
||||||
directives: Map<String, String>
|
directives: Map<String, String>
|
||||||
) {
|
) {
|
||||||
private val diagnosedRanges = Lists.newArrayList<CheckerTestUtil.DiagnosedRange>()
|
private val diagnosedRanges: List<CheckerTestUtil.DiagnosedRange> = ArrayList()
|
||||||
val expectedText: String
|
val expectedText: String
|
||||||
private val clearText: String
|
private val clearText: String
|
||||||
val jetFile: KtFile?
|
val ktFile: KtFile?
|
||||||
private val whatDiagnosticsToConsider: Condition<Diagnostic>
|
private val whatDiagnosticsToConsider: Condition<Diagnostic>
|
||||||
val customLanguageVersionSettings: LanguageVersionSettings
|
val customLanguageVersionSettings: LanguageVersionSettings?
|
||||||
private val declareCheckType: Boolean
|
val declareCheckType: Boolean
|
||||||
private val declareFlexibleType: Boolean
|
val declareFlexibleType: Boolean
|
||||||
val checkLazyLog: Boolean
|
val checkLazyLog: Boolean
|
||||||
private val markDynamicCalls: Boolean
|
private val markDynamicCalls: Boolean
|
||||||
val dynamicCallDescriptors: List<DeclarationDescriptor> = ArrayList()
|
val dynamicCallDescriptors: List<DeclarationDescriptor> = ArrayList()
|
||||||
@@ -160,46 +135,43 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
init {
|
init {
|
||||||
this.whatDiagnosticsToConsider = parseDiagnosticFilterDirective(directives)
|
this.whatDiagnosticsToConsider = parseDiagnosticFilterDirective(directives)
|
||||||
this.customLanguageVersionSettings = parseLanguageVersionSettings(directives)
|
this.customLanguageVersionSettings = parseLanguageVersionSettings(directives)
|
||||||
this.checkLazyLog = directives.containsKey(CHECK_LAZY_LOG_DIRECTIVE) || CHECK_LAZY_LOG_DEFAULT
|
this.checkLazyLog = CHECK_LAZY_LOG_DIRECTIVE in directives || CHECK_LAZY_LOG_DEFAULT
|
||||||
this.declareCheckType = directives.containsKey(CHECK_TYPE_DIRECTIVE)
|
this.declareCheckType = CHECK_TYPE_DIRECTIVE in directives
|
||||||
this.declareFlexibleType = directives.containsKey(EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE)
|
this.declareFlexibleType = EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE in directives
|
||||||
this.markDynamicCalls = directives.containsKey(MARK_DYNAMIC_CALLS_DIRECTIVE)
|
this.markDynamicCalls = MARK_DYNAMIC_CALLS_DIRECTIVE in directives
|
||||||
if (fileName.endsWith(".java")) {
|
if (fileName.endsWith(".java")) {
|
||||||
PsiFileFactory.getInstance(project).createFileFromText(fileName, JavaLanguage.INSTANCE, textWithMarkers)
|
PsiFileFactory.getInstance(project).createFileFromText(fileName, JavaLanguage.INSTANCE, textWithMarkers)
|
||||||
// TODO: check there's not syntax errors
|
// TODO: check there's not syntax errors
|
||||||
this.jetFile = null
|
this.ktFile = null
|
||||||
this.clearText = textWithMarkers
|
this.clearText = textWithMarkers
|
||||||
this.expectedText = this.clearText
|
this.expectedText = this.clearText
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.expectedText = textWithMarkers
|
this.expectedText = textWithMarkers
|
||||||
val textWithExtras = addExtras(expectedText)
|
this.clearText = CheckerTestUtil.parseDiagnosedRanges(addExtras(expectedText), diagnosedRanges)
|
||||||
this.clearText = CheckerTestUtil.parseDiagnosedRanges(textWithExtras, diagnosedRanges)
|
this.ktFile = TestCheckerUtil.createCheckAndReturnPsiFile(fileName, clearText, project)
|
||||||
this.jetFile = TestCheckerUtil.createCheckAndReturnPsiFile(fileName, clearText, project)
|
|
||||||
for (diagnosedRange in diagnosedRanges) {
|
for (diagnosedRange in diagnosedRanges) {
|
||||||
diagnosedRange.file = jetFile
|
diagnosedRange.file = ktFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val imports: String
|
private val imports: String
|
||||||
get() {
|
get() = buildString {
|
||||||
var imports = ""
|
// Line separator is "\n" intentionally here (see DocumentImpl.assertValidSeparators)
|
||||||
if (declareCheckType) {
|
if (declareCheckType) {
|
||||||
imports += CHECK_TYPE_IMPORT + "\n"
|
append(CHECK_TYPE_IMPORT + "\n")
|
||||||
}
|
}
|
||||||
if (declareFlexibleType) {
|
if (declareFlexibleType) {
|
||||||
imports += EXPLICIT_FLEXIBLE_TYPES_IMPORT + "\n"
|
append(EXPLICIT_FLEXIBLE_TYPES_IMPORT + "\n")
|
||||||
}
|
}
|
||||||
return imports
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val extras: String
|
private val extras: String
|
||||||
get() = "/*extras*/\n$imports/*extras*/\n\n"
|
get() = "/*extras*/\n$imports/*extras*/\n\n"
|
||||||
|
|
||||||
private fun addExtras(text: String): String {
|
private fun addExtras(text: String): String =
|
||||||
return addImports(text, extras)
|
addImports(text, extras)
|
||||||
}
|
|
||||||
|
|
||||||
private fun stripExtras(actualText: StringBuilder) {
|
private fun stripExtras(actualText: StringBuilder) {
|
||||||
val extras = extras
|
val extras = extras
|
||||||
@@ -210,22 +182,22 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addImports(text: String, imports: String): String {
|
private fun addImports(text: String, imports: String): String {
|
||||||
var text = text
|
var result = text
|
||||||
val pattern = Pattern.compile("^package [\\.\\w\\d]*\n", Pattern.MULTILINE)
|
val pattern = Pattern.compile("^package [\\.\\w\\d]*\n", Pattern.MULTILINE)
|
||||||
val matcher = pattern.matcher(text)
|
val matcher = pattern.matcher(result)
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
// add imports after the package directive
|
// add imports after the package directive
|
||||||
text = text.substring(0, matcher.end()) + imports + text.substring(matcher.end())
|
result = result.substring(0, matcher.end()) + imports + result.substring(matcher.end())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// add imports at the beginning
|
// add imports at the beginning
|
||||||
text = imports + text
|
result = imports + result
|
||||||
}
|
}
|
||||||
return text
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getActualText(bindingContext: BindingContext, actualText: StringBuilder, skipJvmSignatureDiagnostics: Boolean): Boolean {
|
fun getActualText(bindingContext: BindingContext, actualText: StringBuilder, skipJvmSignatureDiagnostics: Boolean): Boolean {
|
||||||
if (this.jetFile == null) {
|
if (this.ktFile == null) {
|
||||||
// TODO: check java files too
|
// TODO: check java files too
|
||||||
actualText.append(this.clearText)
|
actualText.append(this.clearText)
|
||||||
return true
|
return true
|
||||||
@@ -238,16 +210,16 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
|
|
||||||
val ok = booleanArrayOf(true)
|
val ok = booleanArrayOf(true)
|
||||||
val diagnostics = ContainerUtil.filter(
|
val diagnostics = ContainerUtil.filter(
|
||||||
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, jetFile, markDynamicCalls, dynamicCallDescriptors).plus(
|
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(
|
||||||
jvmSignatureDiagnostics),
|
bindingContext, ktFile, markDynamicCalls, dynamicCallDescriptors
|
||||||
|
) + jvmSignatureDiagnostics,
|
||||||
whatDiagnosticsToConsider
|
whatDiagnosticsToConsider
|
||||||
)
|
)
|
||||||
|
|
||||||
val diagnosticToExpectedDiagnostic = ContainerUtil.newHashMap<Diagnostic, CheckerTestUtil.TextDiagnostic>()
|
val diagnosticToExpectedDiagnostic = hashMapOf<Diagnostic, CheckerTestUtil.TextDiagnostic>()
|
||||||
CheckerTestUtil.diagnosticsDiff(diagnosticToExpectedDiagnostic, diagnosedRanges, diagnostics, object : CheckerTestUtil.DiagnosticDiffCallbacks {
|
CheckerTestUtil.diagnosticsDiff(diagnosticToExpectedDiagnostic, diagnosedRanges, diagnostics, object : CheckerTestUtil.DiagnosticDiffCallbacks {
|
||||||
|
|
||||||
override fun missingDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, expectedStart: Int, expectedEnd: Int) {
|
override fun missingDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, expectedStart: Int, expectedEnd: Int) {
|
||||||
val message = "Missing " + diagnostic.name + DiagnosticUtils.atLocation(jetFile, TextRange(expectedStart, expectedEnd))
|
val message = "Missing " + diagnostic.name + DiagnosticUtils.atLocation(ktFile, TextRange(expectedStart, expectedEnd))
|
||||||
System.err.println(message)
|
System.err.println(message)
|
||||||
ok[0] = false
|
ok[0] = false
|
||||||
}
|
}
|
||||||
@@ -258,21 +230,23 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
start: Int,
|
start: Int,
|
||||||
end: Int
|
end: Int
|
||||||
) {
|
) {
|
||||||
val message = "Parameters of diagnostic not equal at position "
|
val message = "Parameters of diagnostic not equal at position " +
|
||||||
+DiagnosticUtils.atLocation(jetFile, TextRange(start, end))
|
DiagnosticUtils.atLocation(ktFile, TextRange(start, end)) +
|
||||||
+". Expected: " + expectedDiagnostic.asString() + ", actual: " + actualDiagnostic.asString()
|
". Expected: ${expectedDiagnostic.asString()}, actual: $actualDiagnostic"
|
||||||
System.err.println(message)
|
System.err.println(message)
|
||||||
ok[0] = false
|
ok[0] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unexpectedDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, actualStart: Int, actualEnd: Int) {
|
override fun unexpectedDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, actualStart: Int, actualEnd: Int) {
|
||||||
val message = "Unexpected " + diagnostic.name + DiagnosticUtils.atLocation(jetFile, TextRange(actualStart, actualEnd))
|
val message = "Unexpected ${diagnostic.name}${DiagnosticUtils.atLocation(ktFile, TextRange(actualStart, actualEnd))}"
|
||||||
System.err.println(message)
|
System.err.println(message)
|
||||||
ok[0] = false
|
ok[0] = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
actualText.append(CheckerTestUtil.addDiagnosticMarkersToText(jetFile, diagnostics, diagnosticToExpectedDiagnostic, Function<PsiFile, String> { file -> file.text }))
|
actualText.append(
|
||||||
|
CheckerTestUtil.addDiagnosticMarkersToText(ktFile, diagnostics, diagnosticToExpectedDiagnostic, { file -> file.text })
|
||||||
|
)
|
||||||
|
|
||||||
stripExtras(actualText)
|
stripExtras(actualText)
|
||||||
|
|
||||||
@@ -281,7 +255,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
|
|
||||||
private fun computeJvmSignatureDiagnostics(bindingContext: BindingContext): Set<Diagnostic> {
|
private fun computeJvmSignatureDiagnostics(bindingContext: BindingContext): Set<Diagnostic> {
|
||||||
val jvmSignatureDiagnostics = HashSet<Diagnostic>()
|
val jvmSignatureDiagnostics = HashSet<Diagnostic>()
|
||||||
val declarations = PsiTreeUtil.findChildrenOfType(jetFile, KtDeclaration::class.java)
|
val declarations = PsiTreeUtil.findChildrenOfType(ktFile, KtDeclaration::class.java)
|
||||||
for (declaration in declarations) {
|
for (declaration in declarations) {
|
||||||
val diagnostics = getJvmSignatureDiagnostics(declaration, bindingContext.diagnostics,
|
val diagnostics = getJvmSignatureDiagnostics(declaration, bindingContext.diagnostics,
|
||||||
GlobalSearchScope.allScope(project)) ?: continue
|
GlobalSearchScope.allScope(project)) ?: continue
|
||||||
@@ -290,16 +264,13 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
return jvmSignatureDiagnostics
|
return jvmSignatureDiagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String = ktFile!!.name
|
||||||
return jetFile!!.name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val DIAGNOSTICS_DIRECTIVE = "DIAGNOSTICS"
|
val DIAGNOSTICS_DIRECTIVE = "DIAGNOSTICS"
|
||||||
val DIAGNOSTICS_PATTERN = Pattern.compile("([\\+\\-!])(\\w+)\\s*")
|
val DIAGNOSTICS_PATTERN: Pattern = Pattern.compile("([\\+\\-!])(\\w+)\\s*")
|
||||||
val DIAGNOSTICS_TO_INCLUDE_ANYWAY: ImmutableSet<DiagnosticFactory<*>> = ImmutableSet.of(
|
val DIAGNOSTICS_TO_INCLUDE_ANYWAY: Set<DiagnosticFactory<*>> = setOf(
|
||||||
Errors.UNRESOLVED_REFERENCE,
|
Errors.UNRESOLVED_REFERENCE,
|
||||||
Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER,
|
Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER,
|
||||||
CheckerTestUtil.SyntaxErrorDiagnosticFactory.INSTANCE,
|
CheckerTestUtil.SyntaxErrorDiagnosticFactory.INSTANCE,
|
||||||
@@ -338,9 +309,10 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
val directives = directiveMap[LANGUAGE_DIRECTIVE]
|
val directives = directiveMap[LANGUAGE_DIRECTIVE]
|
||||||
if (apiVersionString == null && directives == null) return null
|
if (apiVersionString == null && directives == null) return null
|
||||||
|
|
||||||
val apiVersion = (if (apiVersionString != null) ApiVersion.parse(apiVersionString) else ApiVersion.LATEST) ?: error("Unknown API version: " + apiVersionString!!)
|
val apiVersion = (if (apiVersionString != null) ApiVersion.parse(apiVersionString) else ApiVersion.LATEST)
|
||||||
|
?: error("Unknown API version: $apiVersionString")
|
||||||
|
|
||||||
val languageFeatures = if (directives == null) emptyMap<LanguageFeature, Boolean>() else collectLanguageFeatureMap(directives)
|
val languageFeatures = directives?.let(this::collectLanguageFeatureMap).orEmpty()
|
||||||
|
|
||||||
return DiagnosticTestLanguageVersionSettings(languageFeatures, apiVersion)
|
return DiagnosticTestLanguageVersionSettings(languageFeatures, apiVersion)
|
||||||
}
|
}
|
||||||
@@ -349,8 +321,8 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
val matcher = LANGUAGE_PATTERN.matcher(directives)
|
val matcher = LANGUAGE_PATTERN.matcher(directives)
|
||||||
if (!matcher.find()) {
|
if (!matcher.find()) {
|
||||||
Assert.fail(
|
Assert.fail(
|
||||||
"Wrong syntax in the '// !" + LANGUAGE_DIRECTIVE + ": ...' directive:\n" +
|
"Wrong syntax in the '// !$LANGUAGE_DIRECTIVE: ...' directive:\n" +
|
||||||
"found: '" + directives + "'\n" +
|
"found: '$directives'\n" +
|
||||||
"Must be '([+-]LanguageFeatureName)+'\n" +
|
"Must be '([+-]LanguageFeatureName)+'\n" +
|
||||||
"where '+' means 'enable' and '-' means 'disable'\n" +
|
"where '+' means 'enable' and '-' means 'disable'\n" +
|
||||||
"and language feature names are names of enum entries in LanguageFeature enum class"
|
"and language feature names are names of enum entries in LanguageFeature enum class"
|
||||||
@@ -361,15 +333,12 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
do {
|
do {
|
||||||
val enable = matcher.group(1) == "+"
|
val enable = matcher.group(1) == "+"
|
||||||
val name = matcher.group(2)
|
val name = matcher.group(2)
|
||||||
val feature = LanguageFeature.fromString(name)
|
val feature = LanguageFeature.fromString(name) ?: throw AssertionError(
|
||||||
if (feature == null) {
|
"Language feature not found, please check spelling: $name\n" +
|
||||||
Assert.fail(
|
"Known features:\n ${LanguageFeature.values().joinToString("\n ")}"
|
||||||
"Language feature not found, please check spelling: " + name + "\n" +
|
)
|
||||||
"Known features:\n " + join(Arrays.asList(*LanguageFeature.values()), "\n ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (values.put(feature, enable) != null) {
|
if (values.put(feature, enable) != null) {
|
||||||
Assert.fail("Duplicate entry for the language feature: " + name)
|
Assert.fail("Duplicate entry for the language feature: $name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (matcher.find())
|
while (matcher.find())
|
||||||
@@ -382,55 +351,57 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<BaseDiagnostics
|
|||||||
if (directives == null) {
|
if (directives == null) {
|
||||||
// If "!API_VERSION" is present, disable the NEWER_VERSION_IN_SINCE_KOTLIN diagnostic.
|
// If "!API_VERSION" is present, disable the NEWER_VERSION_IN_SINCE_KOTLIN diagnostic.
|
||||||
// Otherwise it would be reported in any non-trivial test on the @SinceKotlin value.
|
// Otherwise it would be reported in any non-trivial test on the @SinceKotlin value.
|
||||||
if (directiveMap.containsKey(API_VERSION_DIRECTIVE)) {
|
if (API_VERSION_DIRECTIVE in directiveMap) {
|
||||||
return Condition { diagnostic -> diagnostic.factory !== Errors.NEWER_VERSION_IN_SINCE_KOTLIN }
|
return Condition { diagnostic -> diagnostic.factory !== Errors.NEWER_VERSION_IN_SINCE_KOTLIN }
|
||||||
}
|
}
|
||||||
return Conditions.alwaysTrue<Diagnostic>()
|
return Conditions.alwaysTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
var condition = Conditions.alwaysTrue<Diagnostic>()
|
var condition = Conditions.alwaysTrue<Diagnostic>()
|
||||||
val matcher = DIAGNOSTICS_PATTERN.matcher(directives)
|
val matcher = DIAGNOSTICS_PATTERN.matcher(directives)
|
||||||
if (!matcher.find()) {
|
if (!matcher.find()) {
|
||||||
Assert.fail("Wrong syntax in the '// !" + DIAGNOSTICS_DIRECTIVE + ": ...' directive:\n" +
|
Assert.fail("Wrong syntax in the '// !$DIAGNOSTICS_DIRECTIVE: ...' directive:\n" +
|
||||||
"found: '" + directives + "'\n" +
|
"found: '$directives'\n" +
|
||||||
"Must be '([+-!]DIAGNOSTIC_FACTORY_NAME|ERROR|WARNING|INFO)+'\n" +
|
"Must be '([+-!]DIAGNOSTIC_FACTORY_NAME|ERROR|WARNING|INFO)+'\n" +
|
||||||
"where '+' means 'include'\n" +
|
"where '+' means 'include'\n" +
|
||||||
" '-' means 'exclude'\n" +
|
" '-' means 'exclude'\n" +
|
||||||
" '!' means 'exclude everything but this'\n" +
|
" '!' means 'exclude everything but this'\n" +
|
||||||
"directives are applied in the order of appearance, i.e. !FOO +BAR means include only FOO and BAR")
|
"directives are applied in the order of appearance, i.e. !FOO +BAR means include only FOO and BAR")
|
||||||
}
|
}
|
||||||
|
|
||||||
var first = true
|
var first = true
|
||||||
do {
|
do {
|
||||||
val operation = matcher.group(1)
|
val operation = matcher.group(1)
|
||||||
val name = matcher.group(2)
|
val name = matcher.group(2)
|
||||||
|
|
||||||
var newCondition: Condition<Diagnostic>
|
val newCondition: Condition<Diagnostic> =
|
||||||
if (ImmutableSet.of("ERROR", "WARNING", "INFO").contains(name)) {
|
if (name in setOf("ERROR", "WARNING", "INFO")) {
|
||||||
val severity = Severity.valueOf(name)
|
Condition { diagnostic -> diagnostic.severity == Severity.valueOf(name) }
|
||||||
newCondition = Condition<Diagnostic> { diagnostic -> diagnostic.severity == severity }
|
}
|
||||||
}
|
else {
|
||||||
else {
|
Condition { diagnostic -> name == diagnostic.factory.name }
|
||||||
newCondition = Condition<Diagnostic> { diagnostic -> name == diagnostic.factory.name }
|
}
|
||||||
}
|
|
||||||
if ("!" == operation) {
|
when (operation) {
|
||||||
if (!first) {
|
"!" -> {
|
||||||
Assert.fail("'" + operation + name + "' appears in a position rather than the first one, " +
|
if (!first) {
|
||||||
"which effectively cancels all the previous filters in this directive")
|
Assert.fail("'$operation$name' appears in a position rather than the first one, " +
|
||||||
|
"which effectively cancels all the previous filters in this directive")
|
||||||
|
}
|
||||||
|
condition = newCondition
|
||||||
}
|
}
|
||||||
condition = newCondition
|
"+" -> condition = Conditions.or(condition, newCondition)
|
||||||
}
|
"-" -> condition = Conditions.and(condition, Conditions.not(newCondition))
|
||||||
else if ("+" == operation) {
|
|
||||||
condition = Conditions.or(condition, newCondition)
|
|
||||||
}
|
|
||||||
else if ("-" == operation) {
|
|
||||||
condition = Conditions.and(condition, Conditions.not(newCondition))
|
|
||||||
}
|
}
|
||||||
first = false
|
first = false
|
||||||
}
|
}
|
||||||
while (matcher.find())
|
while (matcher.find())
|
||||||
|
|
||||||
// We always include UNRESOLVED_REFERENCE and SYNTAX_ERROR because they are too likely to indicate erroneous test data
|
// We always include UNRESOLVED_REFERENCE and SYNTAX_ERROR because they are too likely to indicate erroneous test data
|
||||||
return Conditions.or(
|
return Conditions.or(
|
||||||
condition,
|
condition,
|
||||||
Condition<Diagnostic> { diagnostic -> DIAGNOSTICS_TO_INCLUDE_ANYWAY.contains(diagnostic.factory) })
|
Condition { diagnostic -> diagnostic.factory in DIAGNOSTICS_TO_INCLUDE_ANYWAY }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import java.lang.reflect.GenericDeclaration
|
|||||||
|
|
||||||
class LoggingStorageManager(
|
class LoggingStorageManager(
|
||||||
private val delegate: StorageManager,
|
private val delegate: StorageManager,
|
||||||
private val callHandler: (lambda: Any, call: LoggingStorageManager.CallData?) -> Unit) : ObservableStorageManager(delegate) {
|
private val callHandler: (lambda: Any, call: LoggingStorageManager.CallData) -> Unit) : ObservableStorageManager(delegate) {
|
||||||
|
|
||||||
class CallData(
|
class CallData(
|
||||||
val fieldOwner: Any?,
|
val fieldOwner: Any?,
|
||||||
|
|||||||
+21
-35
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.checkers
|
|||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.context.ModuleContext
|
import org.jetbrains.kotlin.context.ModuleContext
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
@@ -29,60 +28,55 @@ import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
|
|||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig
|
import org.jetbrains.kotlin.js.config.JsConfig
|
||||||
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig
|
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig
|
||||||
import org.jetbrains.kotlin.js.resolve.*
|
|
||||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||||
|
import org.jetbrains.kotlin.js.resolve.MODULE_KIND
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
|
|
||||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
|
import java.util.*
|
||||||
import java.util.ArrayList
|
import kotlin.reflect.jvm.javaField
|
||||||
|
|
||||||
abstract class AbstractDiagnosticsTestWithJsStdLib : AbstractDiagnosticsTest() {
|
abstract class AbstractDiagnosticsTestWithJsStdLib : AbstractDiagnosticsTest() {
|
||||||
protected var config: JsConfig? = null
|
protected lateinit var config: JsConfig
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
val configuration = environment.configuration.copy()
|
config = LibrarySourcesConfig(project, environment.configuration.copy().apply {
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, KotlinTestUtils.TEST_MODULE_NAME)
|
put(CommonConfigurationKeys.MODULE_NAME, KotlinTestUtils.TEST_MODULE_NAME)
|
||||||
configuration.put(JSConfigurationKeys.LIBRARY_FILES, LibrarySourcesConfig.JS_STDLIB)
|
put(JSConfigurationKeys.LIBRARY_FILES, LibrarySourcesConfig.JS_STDLIB)
|
||||||
config = LibrarySourcesConfig(project, configuration)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
override fun tearDown() {
|
override fun tearDown() {
|
||||||
config = null
|
(AbstractDiagnosticsTestWithJsStdLib::config).javaField!!.set(this, null)
|
||||||
super.tearDown()
|
super.tearDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEnvironmentConfigFiles(): List<String> {
|
override fun getEnvironmentConfigFiles(): List<String> = EnvironmentConfigFiles.JS_CONFIG_FILES
|
||||||
return EnvironmentConfigFiles.JS_CONFIG_FILES
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun analyzeModuleContents(
|
override fun analyzeModuleContents(
|
||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
ktFiles: List<KtFile>,
|
files: List<KtFile>,
|
||||||
moduleTrace: BindingTrace,
|
moduleTrace: BindingTrace,
|
||||||
languageVersionSettings: LanguageVersionSettings?,
|
languageVersionSettings: LanguageVersionSettings?,
|
||||||
separateModules: Boolean
|
separateModules: Boolean
|
||||||
): JsAnalysisResult {
|
): JsAnalysisResult {
|
||||||
// TODO: support LANGUAGE directive in JS diagnostic tests
|
// TODO: support LANGUAGE directive in JS diagnostic tests
|
||||||
assert(languageVersionSettings == null) { BaseDiagnosticsTest.LANGUAGE_DIRECTIVE + " directive is not supported in JS diagnostic tests" }
|
assert(languageVersionSettings == null) { "$LANGUAGE_DIRECTIVE directive is not supported in JS diagnostic tests" }
|
||||||
moduleTrace.record<ModuleDescriptor, ModuleKind>(MODULE_KIND, moduleContext.module, getModuleKind(ktFiles))
|
moduleTrace.record<ModuleDescriptor, ModuleKind>(MODULE_KIND, moduleContext.module, getModuleKind(files))
|
||||||
return TopDownAnalyzerFacadeForJS.analyzeFilesWithGivenTrace(ktFiles, moduleTrace, moduleContext, config!!)
|
return TopDownAnalyzerFacadeForJS.analyzeFilesWithGivenTrace(files, moduleTrace, moduleContext, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getModuleKind(ktFiles: List<KtFile>): ModuleKind {
|
private fun getModuleKind(ktFiles: List<KtFile>): ModuleKind {
|
||||||
var kind = ModuleKind.PLAIN
|
var kind = ModuleKind.PLAIN
|
||||||
for (file in ktFiles) {
|
for (file in ktFiles) {
|
||||||
val text = file.text
|
val text = file.text
|
||||||
for (line in StringUtil.splitByLines(text)) {
|
for (textLine in StringUtil.splitByLines(text)) {
|
||||||
line = line.trim { it <= ' ' }
|
var line = textLine.trim { it <= ' ' }
|
||||||
if (!line.startsWith("//")) continue
|
if (!line.startsWith("//")) continue
|
||||||
line = line.substring(2).trim { it <= ' ' }
|
line = line.substring(2).trim { it <= ' ' }
|
||||||
val parts = StringUtil.split(line, ":")
|
val parts = StringUtil.split(line, ":")
|
||||||
@@ -96,21 +90,13 @@ abstract class AbstractDiagnosticsTestWithJsStdLib : AbstractDiagnosticsTest() {
|
|||||||
return kind
|
return kind
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAdditionalDependencies(module: ModuleDescriptorImpl): List<ModuleDescriptorImpl> {
|
override fun getAdditionalDependencies(module: ModuleDescriptorImpl): List<ModuleDescriptorImpl> =
|
||||||
val dependencies = ArrayList<ModuleDescriptorImpl>()
|
config.moduleDescriptors.map { it.data }
|
||||||
for (moduleDescriptor in config!!.moduleDescriptors) {
|
|
||||||
dependencies.add(moduleDescriptor.data)
|
|
||||||
}
|
|
||||||
return dependencies
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shouldSkipJvmSignatureDiagnostics(groupedByModule: Map<BaseDiagnosticsTest.TestModule, List<BaseDiagnosticsTest.TestFile>>): Boolean {
|
override fun shouldSkipJvmSignatureDiagnostics(groupedByModule: Map<TestModule?, List<TestFile>>): Boolean = true
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createModule(moduleName: String, storageManager: StorageManager): ModuleDescriptorImpl {
|
override fun createModule(moduleName: String, storageManager: StorageManager): ModuleDescriptorImpl =
|
||||||
return ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, JsPlatform.builtIns)
|
ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, JsPlatform.builtIns)
|
||||||
}
|
|
||||||
|
|
||||||
override fun createSealedModule(storageManager: StorageManager): ModuleDescriptorImpl {
|
override fun createSealedModule(storageManager: StorageManager): ModuleDescriptorImpl {
|
||||||
val module = createModule("kotlin-js-test-module", storageManager)
|
val module = createModule("kotlin-js-test-module", storageManager)
|
||||||
|
|||||||
+3
-3
@@ -28,17 +28,17 @@ import org.jetbrains.kotlin.resolve.BindingTrace
|
|||||||
abstract class AbstractDiagnosticsTestWithJsStdLibAndBackendCompilation : AbstractDiagnosticsTestWithJsStdLib() {
|
abstract class AbstractDiagnosticsTestWithJsStdLibAndBackendCompilation : AbstractDiagnosticsTestWithJsStdLib() {
|
||||||
override fun analyzeModuleContents(
|
override fun analyzeModuleContents(
|
||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
ktFiles: MutableList<KtFile>,
|
files: List<KtFile>,
|
||||||
moduleTrace: BindingTrace,
|
moduleTrace: BindingTrace,
|
||||||
languageVersionSettings: LanguageVersionSettings?,
|
languageVersionSettings: LanguageVersionSettings?,
|
||||||
separateModules: Boolean
|
separateModules: Boolean
|
||||||
): JsAnalysisResult {
|
): JsAnalysisResult {
|
||||||
val analysisResult = super.analyzeModuleContents(moduleContext, ktFiles, moduleTrace, languageVersionSettings, separateModules)
|
val analysisResult = super.analyzeModuleContents(moduleContext, files, moduleTrace, languageVersionSettings, separateModules)
|
||||||
val diagnostics = analysisResult.bindingTrace.bindingContext.diagnostics
|
val diagnostics = analysisResult.bindingTrace.bindingContext.diagnostics
|
||||||
|
|
||||||
if (!hasError(diagnostics)) {
|
if (!hasError(diagnostics)) {
|
||||||
val translator = K2JSTranslator(config)
|
val translator = K2JSTranslator(config)
|
||||||
translator.translate(ktFiles, MainCallParameters.noCall(), analysisResult)
|
translator.translate(files, MainCallParameters.noCall(), analysisResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
return analysisResult
|
return analysisResult
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ import java.io.File
|
|||||||
abstract class AbstractPsi2IrDiagnosticsTest : AbstractDiagnosticsTest() {
|
abstract class AbstractPsi2IrDiagnosticsTest : AbstractDiagnosticsTest() {
|
||||||
override fun performAdditionalChecksAfterDiagnostics(
|
override fun performAdditionalChecksAfterDiagnostics(
|
||||||
testDataFile: File,
|
testDataFile: File,
|
||||||
testFiles: MutableList<TestFile>,
|
testFiles: List<TestFile>,
|
||||||
moduleFiles: MutableMap<TestModule?, MutableList<TestFile>>,
|
moduleFiles: Map<TestModule?, List<TestFile>>,
|
||||||
moduleDescriptors: MutableMap<TestModule?, ModuleDescriptorImpl>,
|
moduleDescriptors: Map<TestModule?, ModuleDescriptorImpl>,
|
||||||
moduleBindings: MutableMap<TestModule?, BindingContext>
|
moduleBindings: Map<TestModule?, BindingContext>
|
||||||
) {
|
) {
|
||||||
val actualIrDump = StringBuilder()
|
val actualIrDump = StringBuilder()
|
||||||
for (module in moduleFiles.keys) {
|
for (module in moduleFiles.keys) {
|
||||||
val ktFiles = moduleFiles[module]?.mapNotNull { it.jetFile } ?: continue
|
val ktFiles = moduleFiles[module]?.mapNotNull { it.ktFile } ?: continue
|
||||||
val moduleDescriptor = moduleDescriptors[module] ?: continue
|
val moduleDescriptor = moduleDescriptors[module] ?: continue
|
||||||
val moduleBindingContext = moduleBindings[module] ?: continue
|
val moduleBindingContext = moduleBindings[module] ?: continue
|
||||||
val irModule = AbstractIrGeneratorTestCase.generateIrModule(ktFiles, moduleDescriptor, moduleBindingContext, true)
|
val irModule = AbstractIrGeneratorTestCase.generateIrModule(ktFiles, moduleDescriptor, moduleBindingContext, true)
|
||||||
|
|||||||
Reference in New Issue
Block a user