2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2018 IBM.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.onap.ccsdk.apps.controllerblueprints.scripts
20 import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
21 import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
22 import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
23 import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
24 import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
25 import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
26 import org.jetbrains.kotlin.cli.common.messages.MessageCollector
27 import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
28 import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
29 import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
30 import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
31 import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer
32 import org.jetbrains.kotlin.config.*
33 import org.slf4j.LoggerFactory
35 import kotlin.script.experimental.api.*
36 import kotlin.script.experimental.host.ScriptingHostConfiguration
37 import kotlin.script.experimental.jvm.util.classpathFromClasspathProperty
38 import kotlin.script.experimental.jvmhost.KJvmCompilerProxy
40 open class BluePrintsCompilerProxy(private val hostConfiguration: ScriptingHostConfiguration) : KJvmCompilerProxy {
42 private val log = LoggerFactory.getLogger(BluePrintsCompilerProxy::class.java)!!
44 override fun compile(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration)
45 : ResultWithDiagnostics<CompiledScript<*>> {
47 val messageCollector = ScriptDiagnosticsMessageCollector()
49 fun failure(vararg diagnostics: ScriptDiagnostic): ResultWithDiagnostics.Failure =
50 ResultWithDiagnostics.Failure(*messageCollector.diagnostics.toTypedArray(), *diagnostics)
55 log.trace("Scripting Host Configuration : $hostConfiguration")
57 setIdeaIoUseFallback()
59 val blueprintSourceCode = script as BluePrintSourceCode
61 val compiledJarFile = blueprintSourceCode.targetJarFile
63 if (!compiledJarFile.exists() || blueprintSourceCode.regenerate) {
65 var environment: KotlinCoreEnvironment? = null
67 val rootDisposable = Disposer.newDisposable()
71 val compilerConfiguration = CompilerConfiguration().apply {
73 put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
74 put(CommonConfigurationKeys.MODULE_NAME, blueprintSourceCode.moduleName)
75 put(JVMConfigurationKeys.OUTPUT_JAR, compiledJarFile)
76 put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false)
78 // Load Current Class loader to Compilation Class loader
79 val currentClassLoader = classpathFromClasspathProperty()
80 currentClassLoader?.forEach {
81 add(CLIConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(it))
84 // Add all Kotlin Sources
85 addKotlinSourceRoots(blueprintSourceCode.blueprintKotlinSources)
87 languageVersionSettings = LanguageVersionSettingsImpl(
88 LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE, mapOf(AnalysisFlags.skipMetadataVersionCheck to true)
92 //log.info("Executing with compiler configuration : $compilerConfiguration")
94 environment = KotlinCoreEnvironment.createForProduction(rootDisposable, compilerConfiguration,
95 EnvironmentConfigFiles.JVM_CONFIG_FILES)
97 // Compile Kotlin Sources
98 val compiled = KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment)
100 val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector,
101 environment.configuration.languageVersionSettings)
103 if (analyzerWithCompilerReport.hasErrors()) {
104 return ResultWithDiagnostics.Failure(messageCollector.diagnostics)
107 rootDisposable.dispose()
111 val res = BluePrintCompiledScript<File>(scriptCompilationConfiguration, compiledJarFile)
113 return ResultWithDiagnostics.Success(res, messageCollector.diagnostics)
115 } catch (ex: Throwable) {
116 return failure(ex.asDiagnostics())
121 class ScriptDiagnosticsMessageCollector : MessageCollector {
123 private val _diagnostics = arrayListOf<ScriptDiagnostic>()
125 val diagnostics: List<ScriptDiagnostic> get() = _diagnostics
127 override fun clear() {
131 override fun hasErrors(): Boolean =
132 _diagnostics.any { it.severity == ScriptDiagnostic.Severity.ERROR }
135 override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
136 val mappedSeverity = when (severity) {
137 CompilerMessageSeverity.EXCEPTION,
138 CompilerMessageSeverity.ERROR -> ScriptDiagnostic.Severity.ERROR
139 CompilerMessageSeverity.STRONG_WARNING,
140 CompilerMessageSeverity.WARNING -> ScriptDiagnostic.Severity.WARNING
141 CompilerMessageSeverity.INFO -> ScriptDiagnostic.Severity.INFO
142 CompilerMessageSeverity.LOGGING -> ScriptDiagnostic.Severity.DEBUG
145 if (mappedSeverity != null) {
146 val mappedLocation = location?.let {
147 if (it.line < 0 && it.column < 0) null // special location created by CompilerMessageLocation.create
148 else SourceCode.Location(SourceCode.Position(it.line, it.column))
150 _diagnostics.add(ScriptDiagnostic(message, mappedSeverity, location?.path, mappedLocation))