Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.common.messages
import com.intellij.openapi.util.io.FileUtil.toSystemDependentName
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.*
import com.intellij.psi.util.PsiFormatUtil
import org.jetbrains.kotlin.analyzer.AbstractAnalyzerWithCompilerReport
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTrackerImpl
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils.sortedDiagnostics
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.load.java.components.TraceBasedErrorReporter
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.AnalyzingUtils
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
class AnalyzerWithCompilerReport(
private val messageCollector: MessageCollector,
private val languageVersionSettings: LanguageVersionSettings
) : AbstractAnalyzerWithCompilerReport {
override lateinit var analysisResult: AnalysisResult
constructor(configuration: CompilerConfiguration) : this(
configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) ?: MessageCollector.NONE,
configuration.languageVersionSettings
)
private fun reportIncompleteHierarchies() {
val bindingContext = analysisResult.bindingContext
val classes = bindingContext.getKeys(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY)
if (!classes.isEmpty()) {
val message = StringBuilder(
"Supertypes of the following classes cannot be resolved. " +
"Please make sure you have the required dependencies in the classpath:\n"
)
for (descriptor in classes) {
val fqName = DescriptorUtils.getFqName(descriptor).asString()
val unresolved = bindingContext.get(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY, descriptor)
assert(unresolved != null && !unresolved.isEmpty()) {
"Incomplete hierarchy should be reported with names of unresolved superclasses: $fqName"
}
message.append(" class ").append(fqName)
.append(", unresolved supertypes: ").append(unresolved!!.joinToString())
.append("\n")
}
messageCollector.report(ERROR, message.toString())
}
}
private fun reportAlternativeSignatureErrors() {
val bc = analysisResult.bindingContext
val descriptorsWithErrors = bc.getKeys(JvmBindingContextSlices.LOAD_FROM_JAVA_SIGNATURE_ERRORS)
if (!descriptorsWithErrors.isEmpty()) {
val message = StringBuilder("The following Java entities have annotations with wrong Kotlin signatures:\n")
for (descriptor in descriptorsWithErrors) {
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)
assert(declaration is PsiModifierListOwner)
val errors = bc.get(JvmBindingContextSlices.LOAD_FROM_JAVA_SIGNATURE_ERRORS, descriptor)
assert(errors != null && !errors.isEmpty())
val externalName = PsiFormatUtil.getExternalName(declaration as PsiModifierListOwner)
message.append(externalName).append(":\n")
for (error in errors!!) {
message.append(" ").append(error).append("\n")
}
}
messageCollector.report(ERROR, message.toString())
}
}
private fun reportSyntaxErrors(files: Collection) {
for (file in files) {
reportSyntaxErrors(file, messageCollector)
}
}
class SyntaxErrorReport(val isHasErrors: Boolean, val isAllErrorsAtEof: Boolean)
override fun hasErrors(): Boolean =
messageCollector.hasErrors()
override fun analyzeAndReport(files: Collection, analyze: () -> AnalysisResult) {
analysisResult = analyze()
ExperimentalUsageChecker.checkCompilerArguments(
analysisResult.moduleDescriptor, languageVersionSettings,
reportError = { message -> messageCollector.report(ERROR, message) },
reportWarning = { message -> messageCollector.report(WARNING, message) }
)
reportSyntaxErrors(files)
reportDiagnostics(analysisResult.bindingContext.diagnostics, messageCollector)
reportIncompleteHierarchies()
reportAlternativeSignatureErrors()
}
private class MyDiagnostic(
psiElement: E, factory: DiagnosticFactory0, val message: String
) : SimpleDiagnostic(psiElement, factory, Severity.ERROR) {
override val isValid: Boolean = true
}
companion object {
fun convertSeverity(severity: Severity): CompilerMessageSeverity = when (severity) {
Severity.INFO -> INFO
Severity.ERROR -> ERROR
Severity.WARNING -> WARNING
else -> throw IllegalStateException("Unknown severity: $severity")
}
private val SYNTAX_ERROR_FACTORY = DiagnosticFactory0.create(Severity.ERROR)
private fun reportDiagnostic(diagnostic: Diagnostic, reporter: DiagnosticMessageReporter): Boolean {
if (!diagnostic.isValid) return false
reporter.report(
diagnostic,
diagnostic.psiFile,
(diagnostic as? MyDiagnostic<*>)?.message ?: DefaultErrorMessages.render(diagnostic)
)
return diagnostic.severity == Severity.ERROR
}
fun reportDiagnostics(unsortedDiagnostics: GenericDiagnostics<*>, reporter: DiagnosticMessageReporter): Boolean {
var hasErrors = false
val diagnostics = sortedDiagnostics(unsortedDiagnostics.all().filterIsInstance())
for (diagnostic in diagnostics) {
hasErrors = hasErrors or reportDiagnostic(diagnostic, reporter)
}
return hasErrors
}
fun reportDiagnostics(diagnostics: GenericDiagnostics<*>, messageCollector: MessageCollector): Boolean {
val hasErrors = reportDiagnostics(diagnostics, DefaultDiagnosticReporter(messageCollector))
if (diagnostics.any { it.factory == Errors.INCOMPATIBLE_CLASS }) {
messageCollector.report(
ERROR,
"Incompatible classes were found in dependencies. " +
"Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors"
)
}
if (diagnostics.any { it.factory == Errors.PRE_RELEASE_CLASS }) {
messageCollector.report(
ERROR,
"Pre-release classes were found in dependencies. " +
"Remove them from the classpath, recompile with a release compiler " +
"or use '-Xskip-prerelease-check' to suppress errors"
)
}
if (diagnostics.any { it.factory == Errors.IR_WITH_UNSTABLE_ABI_COMPILED_CLASS }) {
messageCollector.report(
ERROR,
"Classes compiled by an unstable version of the Kotlin compiler were found in dependencies. " +
"Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors"
)
}
if (diagnostics.any { it.factory == Errors.FIR_COMPILED_CLASS }) {
messageCollector.report(
ERROR,
"Classes compiled by the new Kotlin compiler frontend were found in dependencies. " +
"Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors"
)
}
return hasErrors
}
fun reportSyntaxErrors(file: PsiElement, reporter: DiagnosticMessageReporter): SyntaxErrorReport {
class ErrorReportingVisitor : AnalyzingUtils.PsiErrorElementVisitor() {
var hasErrors = false
var allErrorsAtEof = true
private fun reportDiagnostic(element: E, factory: DiagnosticFactory0, message: String) {
val diagnostic = MyDiagnostic(element, factory, message)
AnalyzerWithCompilerReport.reportDiagnostic(diagnostic, reporter)
if (allErrorsAtEof && !element.isAtEof()) {
allErrorsAtEof = false
}
hasErrors = true
}
private fun PsiElement.isAtEof(): Boolean {
var element = this
while (true) {
element = element.nextSibling ?: return true
if (element !is PsiWhiteSpace || element !is PsiComment) return false
}
}
override fun visitErrorElement(element: PsiErrorElement) {
val description = element.errorDescription
reportDiagnostic(
element, SYNTAX_ERROR_FACTORY,
if (StringUtil.isEmpty(description)) "Syntax error" else description
)
}
}
val visitor = ErrorReportingVisitor()
file.accept(visitor)
return SyntaxErrorReport(visitor.hasErrors, visitor.allErrorsAtEof)
}
fun reportSyntaxErrors(file: PsiElement, messageCollector: MessageCollector): SyntaxErrorReport {
return reportSyntaxErrors(file, DefaultDiagnosticReporter(messageCollector))
}
fun reportBytecodeVersionErrors(bindingContext: BindingContext, messageCollector: MessageCollector) {
val severity =
if (System.getProperty("kotlin.jvm.disable.bytecode.version.error") == "true") STRONG_WARNING
else ERROR
val locations = bindingContext.getKeys(IncompatibleClassTrackerImpl.BYTECODE_VERSION_ERRORS)
if (locations.isEmpty()) return
for (location in locations) {
val data = bindingContext.get(IncompatibleClassTrackerImpl.BYTECODE_VERSION_ERRORS, location)
?: error("Value is missing for key in binding context: $location")
reportIncompatibleBinaryVersion(messageCollector, data, severity)
}
}
private fun reportIncompatibleBinaryVersion(
messageCollector: MessageCollector,
data: IncompatibleVersionErrorData,
severity: CompilerMessageSeverity
) {
messageCollector.report(
severity,
"Class '" + JvmClassName.byClassId(data.classId) + "' was compiled with an incompatible version of Kotlin. " +
"The binary version of its bytecode is " + data.actualVersion + ", expected version is " + data.expectedVersion,
CompilerMessageLocation.create(toSystemDependentName(data.filePath))
)
}
}
}