Compare commits

...

44 Commits

Author SHA1 Message Date
Ilya Gorbunov
64db423b8b Provide JvmSynthetic annotation in stdlib-common as optional 2018-08-27 15:24:55 +03:00
Ilya Gorbunov
7dc19af994 Introduce platform specific annotations as optional in common stdlib 2018-08-27 15:24:55 +03:00
Ilya Gorbunov
8165e4546f Move OptionalExpectation and related annotations to another source root 2018-08-27 15:24:55 +03:00
Sergey Igushkin
3cc01632a0 Always apply the java-base plugin from the new MPP plugin
This fixes misconfigured test tasks and the `Usage` attribute
compatibility rule missing that is added by `java-base`.

Issue #KT-26301 Fixed

(cherry picked from commit ef85fe7ab2)
2018-08-27 14:15:35 +03:00
Sergey Igushkin
e4916a8f80 Add missing Gradle task input path sensitivity
Fix after the commit 0f003802f

(cherry picked from commit 2040cdde4b)
2018-08-27 14:15:35 +03:00
Sergey Igushkin
2e9182cefc Fix the SourceSet.projectDefault() extension adding sources to resources
The `include` calls were effectively made on the `resources`
`SourceDirectorySet`, which meant including '**' from 'src' as well.

Since the 'SourceDirectorySet' API is quite limited and does not support
specifying includes/excludes separately, configure the
`ProcessResources` task instead.

(cherry picked from commit a71c66a82f)
2018-08-27 14:15:35 +03:00
Sergey Igushkin
098cfe7967 Fix Kotlin source directories not added into the Java source set srcDirs
Before the new MPP, Kotlin source directories were added to the Java
source set's `allJava` and `allSource` by all of the Kotlin plugins,
including common and JS ones. As it turned out, this was required by the
IntelliJ Gradle import.

* Make all `KotlinSourceSetProcessor`s (not just JVM) check whether a
  compilation has a Java source set and add the Kotlin source
  directories to `allSource` and `allJava`

* Also disable the unclear resource `exclude` for the Java source set
  that filters Kotlin source directories out of the resources

Issue #KT-26020 Fixed
Issue #KT-26267 Fixed

(cherry picked from commit 674e464230)
2018-08-27 14:15:35 +03:00
Sergey Igushkin
5f6b997894 Revert "Fix source set resources filtering broken by refactoring"
This reverts commit 6af6834

(cherry picked from commit b125f1e23e)
2018-08-27 14:15:34 +03:00
Sergey Igushkin
d53a28de26 Enable metadata publishing for new MPP and consumption from source sets
* Add configurations for consuming source sets metadata (extending the
  source set's dependency configurations). These configurations will be
  used by the IDE to pick up the dependencies metadata.

* Remove the universal preset from the default presets, create a
  metadata target by default for compiling and publishing the metadata
  of `commonMain` (in the future, we will publish and consume the
  metadata of the other source sets as well).

* Make the classpath configurations of common modules consume the
  metadata and thus ensure compatibility of 1.2.x MPP with the new MPP
  model.

(cherry picked from commit 1a3dd67176)
2018-08-27 14:15:34 +03:00
Alexander Podkhalyuzin
4949ff3e63 Added Kotlin svg icon to the distribution
#KT-26393 Fixed

(cherry picked from commit 54922362e3)
2018-08-25 17:59:22 +03:00
Alexander Podkhalyuzin
e062be9fb3 Added resolve scope enlarger to module infos in Kotlin
From now it's possible to enlarge resolve scope for analysis in IDE,
the only difference is that it's based on module file.

#KT-26313 Fixed

(cherry picked from commit c0e92ba350)
2018-08-25 12:21:04 +03:00
Juan Chen
cfcecbd389 Add sync after Kotlin configured in Android Studio projects.
(cherry picked from commit 1a562d477a)
2018-08-24 22:26:49 +03:00
Yan Zhulanow
926e6ba1b5 Parcelize, Minor: Fix tests (writeToParcel/describeContents are not final anymore)
(cherry picked from commit d0fd74982d)
2018-08-24 04:30:34 +05:00
Yan Zhulanow
1a6c860595 Kapt: Ignore annotation-processing-gradle compiler plugin we got from Gradle (KT-24714)
Cause it's built for the shaded Kotlin compiler and won't work with JPS.

(cherry picked from commit d08a32c7cb)
2018-08-24 04:30:13 +05:00
Yan Zhulanow
58f852ff3f Parcelize: Fix infinite recursive loop for zero-parameter Parcelable classes (KT-25839)
(cherry picked from commit 8c05769745)
2018-08-24 04:30:09 +05:00
Anton Bannykh
a43ea8f7ca JS: don't throw AssertionError from RedundantCallElimination
Also mark JS `call` function to avoid removing a custom `call`

(cherry picked from commit 4e496cf2b2)
2018-08-23 14:45:43 +03:00
Nicolay Mitropolsky
9a56ba49fc CreateCallableFromUsageFix always calls openInEditor to force proper editor and focus
(cherry picked from commit 9eb612a605)
2018-08-23 09:27:53 +03:00
Nicolay Mitropolsky
2a9ceef833 KotlinElementActionsFactory uses createAddMethodActions to create properties
(cherry picked from commit 18db40474a)
2018-08-23 09:21:56 +03:00
Alexey Tsvetkov
a443476918 Recompile all subclasses of changed classes
Previously inter-project IC recompiled only direct subclasses
of changed classes

    #KT-25455 fixed
2018-08-22 00:18:01 +03:00
Alexey Tsvetkov
e5a0d4e761 Use file trees in InspectClassesForMultiModuleIC
#KT-26208
2018-08-22 00:18:01 +03:00
Alexey Tsvetkov
e71c868620 Minor: remove redundant default argument 'weakTesting = false' 2018-08-22 00:18:01 +03:00
Alexey Tsvetkov
a69ca81c26 Minor: remove GradleICReporter 2018-08-22 00:18:00 +03:00
Alexey Tsvetkov
44e17f74a3 Implement inter-project JS IC with Gradle
#KT-25025 fixed
2018-08-22 00:18:00 +03:00
Alexey Tsvetkov
b024c997ca Minor: move tests for incremental compilation of Kotlin when Java changes 2018-08-22 00:18:00 +03:00
Alexey Tsvetkov
9f43922eb2 Refactoring: extract function for getting classpath changes 2018-08-22 00:17:59 +03:00
Alexey Tsvetkov
3a76611b95 Refactoring: introduce DirtyFilesContainer for better code reuse in IC 2018-08-22 00:17:59 +03:00
Alexey Tsvetkov
aaad2d589c Avoid rebuild when '--verbose' is used in Gradle
#KT-23472 fixed
2018-08-22 00:17:59 +03:00
Alexey Tsvetkov
b98aeeb77c Use same system property to avoid deleting module file in JPS and Gradle 2018-08-22 00:17:59 +03:00
Anton Bannykh
edeba28e84 JS: fix complex nested cross-module inlining (KT-26117 fixed)
(cherry picked from commit 04b04f919d)
2018-08-21 20:42:48 +03:00
Alexander Udalov
b0757e3080 Use kotlinx-metadata-jvm of version 0.0.4 in kotlin-reflect build script
To prevent various problems with non-shaded artifact (shading was added
in 0.0.3)

(cherry picked from commit e41e28271b)
2018-08-21 17:13:13 +02:00
Alexander Udalov
3ccdb9f2a9 Report error on incompatible .kotlin_module files in classpath
Also remove obsolete test wrongAbiVersionNoErrors

 #KT-25973 Fixed
 #KT-26266 Open

(cherry picked from commit 852760b3b0)
2018-08-21 17:13:00 +02:00
Alexander Udalov
e0126f9036 Report error instead of throwing exception in JvmPackagePartProvider
(cherry picked from commit 4f11812668)
2018-08-21 17:12:57 +02:00
Vyacheslav Gerasimov
d0ea36b2ab as33: Restore gradle-java.xml 2018-08-21 17:48:19 +03:00
Vyacheslav Gerasimov
fc5a56983d as33: Add missing GooglePluginUpdateVerifier 2018-08-21 16:38:06 +03:00
Alexander Udalov
8c7db2a8d0 Fix compilation in KotlinTestUtils for IDEA 173
(cherry picked from commit 3442c7385f)
2018-08-21 14:05:51 +02:00
Alexander Udalov
3857775684 Fix compilation in KotlinTestUtils for AS 3.1 & 3.2
(cherry picked from commit 97c0f1712a)
2018-08-21 14:05:49 +02:00
Alexander Udalov
cca12ac647 Minor, use resolveSibling in getAbsolutePaths
(cherry picked from commit f069686a14)
2018-08-21 13:04:03 +02:00
Alexander Udalov
de1aada638 Disallow using optional annotations outside common module sources
#KT-25196 Fixed

(cherry picked from commit e56374908e)
2018-08-21 13:04:01 +02:00
Alexander Udalov
7b87d2bfc3 Introduce -Xcommon-sources and pass it correctly from build tool plugins
#KT-25196 In Progress

(cherry picked from commit 0f003802fe)
2018-08-21 13:03:55 +02:00
Svyatoslav Kuzmich
e238423425 [JS BE] KT-22053 Fix constructor delegation of immediate subtype of Error 2018-08-20 13:43:02 +03:00
Nikolay Krasko
f730f14d0d Workaround for IndexNotReadyException from icon provider (EA-118965)
Provider is DumbAware and isn't expected to access indexes.

(cherry picked from commit 8f566132e4)
2018-08-19 17:49:32 +03:00
Anton Bannykh
cf53922f1f JS: create appropriate nameBinding's upon inlining
Otherwise JsName's don't get linked properly upon deserialization.
As a result a function/constructor doesn't get renamed at
call site during the name conflict resolution phase.

(cherry picked from commit 8e5b2fe657)
2018-08-17 15:29:17 +03:00
Alexey Tsvetkov
b81c590e12 Add test for KT-26064
(cherry picked from commit 3b4a49eebf)
2018-08-17 15:28:24 +03:00
Vyacheslav Gerasimov
ed0a79e556 Add changelog for 1.2.70 EAP 1 2018-08-17 14:43:26 +03:00
189 changed files with 2430 additions and 6846 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -34,11 +34,14 @@ import org.jetbrains.kotlin.synthetic.SAM_LOOKUP_NAME
import java.io.File
import java.util.*
const val DELETE_MODULE_FILE_PROPERTY = "kotlin.delete.module.file.after.build"
fun makeModuleFile(
name: String,
isTest: Boolean,
outputDir: File,
sourcesToCompile: Iterable<File>,
commonSources: Iterable<File>,
javaSourceRoots: Iterable<JvmSourceRoot>,
classpath: Iterable<File>,
friendDirs: Iterable<File>
@@ -53,6 +56,7 @@ fun makeModuleFile(
sourcesToCompile.map { it.absoluteFile },
javaSourceRoots,
classpath,
commonSources.map { it.absoluteFile },
null,
"java-production",
isTest,
@@ -130,6 +134,7 @@ fun ChangesCollector.getDirtyData(
if (change is ChangeInfo.SignatureChanged) {
val fqNames = if (!change.areSubclassesAffected) listOf(change.fqName) else withSubtypes(change.fqName, caches)
dirtyClassesFqNames.addAll(fqNames)
for (classFqName in fqNames) {
assert(!classFqName.isRoot) { "$classFqName is root when processing $change" }

View File

@@ -34,16 +34,18 @@ class KotlinModuleXmlBuilder {
}
fun addModule(
moduleName: String,
outputDir: String,
sourceFiles: Iterable<File>,
javaSourceRoots: Iterable<JvmSourceRoot>,
classpathRoots: Iterable<File>,
modularJdkRoot: File?,
targetTypeId: String,
isTests: Boolean,
directoriesToFilterOut: Set<File>,
friendDirs: Iterable<File>): KotlinModuleXmlBuilder {
moduleName: String,
outputDir: String,
sourceFiles: Iterable<File>,
javaSourceRoots: Iterable<JvmSourceRoot>,
classpathRoots: Iterable<File>,
commonSourceFiles: Iterable<File>,
modularJdkRoot: File?,
targetTypeId: String,
isTests: Boolean,
directoriesToFilterOut: Set<File>,
friendDirs: Iterable<File>
): KotlinModuleXmlBuilder {
assert(!done) { "Already done" }
p.println("<!-- Module script for ${if (isTests) "tests" else "production"} -->")
@@ -62,6 +64,10 @@ class KotlinModuleXmlBuilder {
p.println("<", SOURCES, " ", PATH, "=\"", getEscapedPath(sourceFile), "\"/>")
}
for (commonSourceFile in commonSourceFiles) {
p.println("<", COMMON_SOURCES, " ", PATH, "=\"", getEscapedPath(commonSourceFile), "\"/>")
}
processJavaSourceRoots(javaSourceRoots)
processClasspath(classpathRoots, directoriesToFilterOut)

View File

@@ -4,6 +4,8 @@ import org.gradle.api.*
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.*
import org.gradle.kotlin.dsl.*
import org.gradle.language.jvm.tasks.ProcessResources
//import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
inline fun Project.sourceSets(crossinline body: SourceSetsBuilder.() -> Unit) =
@@ -25,18 +27,20 @@ fun SourceSet.none() {
resources.setSrcDirs(emptyList<String>())
}
fun SourceSet.projectDefault() {
when (name) {
"main" -> {
java.srcDirs("src")
resources.srcDir("resources").apply { include("**") }
resources.srcDir("src").apply { include("META-INF/**", "**/*.properties") }
}
"test" -> {
java.srcDirs("test", "tests")
val SourceSet.projectDefault: Project.() -> Unit
get() = {
when (this@projectDefault.name) {
"main" -> {
java.srcDirs("src")
val processResources = tasks.getByName(processResourcesTaskName) as ProcessResources
processResources.from("resources") { include("**") }
processResources.from("src") { include("META-INF/**", "**/*.properties") }
}
"test" -> {
java.srcDirs("test", "tests")
}
}
}
}
// TODO: adding KotlinSourceSet dep to the plugin breaks the build unexpectedly, resolve and uncomment
//val SourceSet.kotlin: SourceDirectorySet

View File

@@ -201,7 +201,9 @@ public class ClassFileFactory implements OutputFileCollection {
case "kotlin_module": {
ModuleMapping mapping = ModuleMappingUtilKt.loadModuleMapping(
ModuleMapping.Companion, file.asByteArray(), relativePath.getPath(),
CompilerDeserializationConfiguration.Default.INSTANCE
CompilerDeserializationConfiguration.Default.INSTANCE, version -> {
throw new IllegalStateException("Version of the generated module cannot be incompatible: " + version);
}
);
for (Map.Entry<String, PackageParts> entry : mapping.getPackageFqName2Parts().entrySet()) {
FqName packageFqName = new FqName(entry.getKey());

View File

@@ -38,7 +38,9 @@ private fun Iterable<PackageParts>.addCompiledParts(state: GenerationState): Lis
val incrementalCache = state.incrementalCacheForThisTarget ?: return this.toList()
val moduleMappingData = incrementalCache.getModuleMappingData() ?: return this.toList()
val mapping = ModuleMapping.loadModuleMapping(moduleMappingData, "<incremental>", state.deserializationConfiguration)
val mapping = ModuleMapping.loadModuleMapping(moduleMappingData, "<incremental>", state.deserializationConfiguration) { version ->
throw IllegalStateException("Version of the generated module cannot be incompatible: $version")
}
incrementalCache.getObsoletePackageParts().forEach { internalName ->
val qualifier = JvmClassName.byInternalName(internalName).packageFqName.asString()

View File

@@ -180,6 +180,14 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
)
var metadataVersion: String? by FreezableVar(null)
@Argument(
value = "-Xcommon-sources",
valueDescription = "<path>",
description = "Sources of the common module that need to be compiled together with this module in the multi-platform mode.\n" +
"Should be a subset of sources passed as free arguments"
)
var commonSources: Array<String>? by FreezableVar(null)
open fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
return HashMap<AnalysisFlag<*>, Any>().apply {
put(AnalysisFlag.skipMetadataVersionCheck, skipMetadataVersionCheck)

View File

@@ -21,11 +21,12 @@ import org.jetbrains.kotlin.modules.Module
import java.util.*
class ModuleBuilder(
private val name: String,
private val outputDir: String,
private val type: String
private val name: String,
private val outputDir: String,
private val type: String
) : Module {
private val sourceFiles = ArrayList<String>()
private val commonSourceFiles = ArrayList<String>()
private val classpathRoots = ArrayList<String>()
private val javaSourceRoots = ArrayList<JavaRootPath>()
private val friendDirs = ArrayList<String>()
@@ -35,6 +36,10 @@ class ModuleBuilder(
sourceFiles.add(path)
}
fun addCommonSourceFiles(path: String) {
commonSourceFiles.add(path)
}
fun addClasspathEntry(path: String) {
classpathRoots.add(path)
}
@@ -51,6 +56,7 @@ class ModuleBuilder(
override fun getFriendPaths(): List<String> = friendDirs
override fun getJavaSourceRoots(): List<JavaRootPath> = javaSourceRoots
override fun getSourceFiles(): List<String> = sourceFiles
override fun getCommonSourceFiles(): List<String> = commonSourceFiles
override fun getClasspathRoots(): List<String> = classpathRoots
override fun getModuleName(): String = name
override fun getModuleType(): String = type

View File

@@ -47,6 +47,7 @@ public class ModuleXmlParser {
public static final String OUTPUT_DIR = "outputDir";
public static final String FRIEND_DIR = "friendDir";
public static final String SOURCES = "sources";
public static final String COMMON_SOURCES = "commonSources";
public static final String JAVA_SOURCE_ROOTS = "javaSourceRoots";
public static final String JAVA_SOURCE_PACKAGE_PREFIX = "packagePrefix";
public static final String PATH = "path";
@@ -159,6 +160,10 @@ public class ModuleXmlParser {
String path = getAttribute(attributes, PATH, qName);
moduleBuilder.addSourceFiles(path);
}
else if (COMMON_SOURCES.equalsIgnoreCase(qName)) {
String path = getAttribute(attributes, PATH, qName);
moduleBuilder.addCommonSourceFiles(path);
}
else if (FRIEND_DIR.equalsIgnoreCase(qName)) {
String path = getAttribute(attributes, PATH, qName);
moduleBuilder.addFriendDir(path);

View File

@@ -10,14 +10,18 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
interface ContentRoot
data class KotlinSourceRoot(val path: String): ContentRoot
/**
* @param isCommon whether this source root contains sources of a common module in a multi-platform project
*/
data class KotlinSourceRoot(val path: String, val isCommon: Boolean): ContentRoot
fun CompilerConfiguration.addKotlinSourceRoot(source: String) {
add(CLIConfigurationKeys.CONTENT_ROOTS, KotlinSourceRoot(source))
@JvmOverloads
fun CompilerConfiguration.addKotlinSourceRoot(path: String, isCommon: Boolean = false) {
add(CLIConfigurationKeys.CONTENT_ROOTS, KotlinSourceRoot(path, isCommon))
}
fun CompilerConfiguration.addKotlinSourceRoots(sources: List<String>): Unit =
sources.forEach(this::addKotlinSourceRoot)
sources.forEach { addKotlinSourceRoot(it) }
val CompilerConfiguration.kotlinSourceRoots: List<String>
get() = get(CLIConfigurationKeys.CONTENT_ROOTS)?.filterIsInstance<KotlinSourceRoot>()?.map { it.path }.orEmpty()
val CompilerConfiguration.kotlinSourceRoots: List<KotlinSourceRoot>
get() = get(CLIConfigurationKeys.CONTENT_ROOTS)?.filterIsInstance<KotlinSourceRoot>().orEmpty()

View File

@@ -26,6 +26,7 @@ import com.intellij.util.ExceptionUtil;
import com.intellij.util.SmartList;
import kotlin.collections.ArraysKt;
import kotlin.collections.CollectionsKt;
import kotlin.collections.SetsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
@@ -175,7 +176,12 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector));
ContentRootsKt.addKotlinSourceRoots(configuration, arguments.getFreeArgs());
String[] commonSourcesArray = arguments.getCommonSources();
Set<String> commonSources = commonSourcesArray == null ? Collections.emptySet() : SetsKt.setOf(commonSourcesArray);
for (String arg : arguments.getFreeArgs()) {
ContentRootsKt.addKotlinSourceRoot(configuration, arg, commonSources.contains(arg));
}
KotlinCoreEnvironment environmentForJS =
KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JS_CONFIG_FILES);

View File

@@ -77,13 +77,14 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
val pluginLoadResult = loadPlugins(arguments, configuration)
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
val commonSources = arguments.commonSources?.toSet().orEmpty()
if (!arguments.script && arguments.buildFile == null) {
for (arg in arguments.freeArgs) {
val file = File(arg)
if (file.extension == JavaFileType.DEFAULT_EXTENSION) {
configuration.addJavaSourceRoot(file)
} else {
configuration.addKotlinSourceRoot(arg)
configuration.addKotlinSourceRoot(arg, isCommon = arg in commonSources)
if (file.isDirectory) {
configuration.addJavaSourceRoot(file)
}

View File

@@ -19,16 +19,23 @@ package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.SmartList
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.LOGGING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.loadModuleMapping
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
import java.io.ByteArrayOutputStream
import java.io.EOFException
import java.io.PrintStream
class JvmPackagePartProvider(
languageVersionSettings: LanguageVersionSettings,
@@ -77,7 +84,7 @@ class JvmPackagePartProvider(
}.flatten()
}
fun addRoots(roots: List<JavaRoot>) {
fun addRoots(roots: List<JavaRoot>, messageCollector: MessageCollector) {
for ((root, type) in roots) {
if (type != JavaRoot.RootType.BINARY) continue
if (root !in scope) continue
@@ -86,12 +93,28 @@ class JvmPackagePartProvider(
for (moduleFile in metaInf.children) {
if (!moduleFile.name.endsWith(ModuleMapping.MAPPING_FILE_EXT)) continue
val mapping = try {
ModuleMapping.loadModuleMapping(moduleFile.contentsToByteArray(), moduleFile.toString(), deserializationConfiguration)
try {
val mapping = ModuleMapping.loadModuleMapping(
moduleFile.contentsToByteArray(), moduleFile.toString(), deserializationConfiguration
) { incompatibleVersion ->
messageCollector.report(
ERROR,
"Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is " +
"$incompatibleVersion, expected version is ${JvmMetadataVersion.INSTANCE}.",
CompilerMessageLocation.create(moduleFile.path)
)
}
loadedModules.add(ModuleMappingInfo(root, mapping, moduleFile.nameWithoutExtension))
} catch (e: EOFException) {
throw RuntimeException("Error on reading package parts from $moduleFile in $root", e)
messageCollector.report(
ERROR, "Error occurred when reading the module: ${e.message}", CompilerMessageLocation.create(moduleFile.path)
)
messageCollector.report(
LOGGING,
String(ByteArrayOutputStream().also { e.printStackTrace(PrintStream(it)) }.toByteArray()),
CompilerMessageLocation.create(moduleFile.path)
)
}
loadedModules.add(ModuleMappingInfo(root, mapping, moduleFile.nameWithoutExtension))
}
}
}

View File

@@ -69,6 +69,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
import org.jetbrains.kotlin.cli.common.config.ContentRoot
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
@@ -110,6 +111,7 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtens
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
import org.jetbrains.kotlin.script.ScriptReportSink
@@ -305,7 +307,7 @@ class KotlinCoreEnvironment private constructor(
fun createPackagePartProvider(scope: GlobalSearchScope): JvmPackagePartProvider {
return JvmPackagePartProvider(configuration.languageVersionSettings, scope).apply {
addRoots(initialRoots)
addRoots(initialRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY))
packagePartProviders += this
(ModuleAnnotationsResolver.getInstance(project) as CliModuleAnnotationsResolver).addPackagePartProvider(this)
}
@@ -363,7 +365,7 @@ class KotlinCoreEnvironment private constructor(
val newRoots = classpathRootsResolver.convertClasspathRoots(contentRoots).roots
for (packagePartProvider in packagePartProviders) {
packagePartProvider.addRoots(newRoots)
packagePartProvider.addRoots(newRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY))
}
return rootsIndex.addNewIndexForRoots(newRoots)?.let { newIndex ->
@@ -400,16 +402,18 @@ class KotlinCoreEnvironment private constructor(
private fun findJarRoot(file: File): VirtualFile? =
applicationEnvironment.jarFileSystem.findFileByPath("$file${URLUtil.JAR_SEPARATOR}")
private fun getSourceRootsCheckingForDuplicates(): Collection<String> {
val uniqueSourceRoots = linkedSetOf<String>()
private fun getSourceRootsCheckingForDuplicates(): List<KotlinSourceRoot> {
val uniqueSourceRoots = hashSetOf<String>()
val result = mutableListOf<KotlinSourceRoot>()
configuration.kotlinSourceRoots.forEach { path ->
if (!uniqueSourceRoots.add(path)) {
report(STRONG_WARNING, "Duplicate source root: $path")
for (root in configuration.kotlinSourceRoots) {
if (!uniqueSourceRoots.add(root.path)) {
report(STRONG_WARNING, "Duplicate source root: ${root.path}")
}
result.add(root)
}
return uniqueSourceRoots
return result
}
fun getSourceFiles(): List<KtFile> = sourceFiles
@@ -425,7 +429,7 @@ class KotlinCoreEnvironment private constructor(
val virtualFileCreator = PreprocessedFileCreator(project)
for (sourceRootPath in sourceRoots) {
for ((sourceRootPath, isCommon) in sourceRoots) {
val vFile = localFileSystem.findFileByPath(sourceRootPath)
if (vFile == null) {
val message = "Source file or directory not found: $sourceRootPath"
@@ -452,6 +456,9 @@ class KotlinCoreEnvironment private constructor(
val psiFile = psiManager.findFile(virtualFile)
if (psiFile is KtFile) {
result.add(psiFile)
if (isCommon) {
psiFile.isCommonSource = true
}
}
}
}

View File

@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
@@ -65,18 +65,6 @@ import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader
object KotlinToJVMBytecodeCompiler {
private fun getAbsoluteFiles(buildFile: File, module: Module): List<File> {
return module.getSourceFiles().map { sourceFile ->
val source = File(sourceFile)
if (!source.isAbsolute) {
File(buildFile.absoluteFile.parentFile, sourceFile)
} else {
source
}
}
}
private fun writeOutput(
configuration: CompilerConfiguration,
outputFiles: OutputFileCollection,
@@ -142,7 +130,7 @@ object KotlinToJVMBytecodeCompiler {
for (module in chunk) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val moduleSourceFiles = getAbsoluteFiles(buildFile, module).map { file -> localFileSystem.findFileByPath(file.path) }
val moduleSourceFiles = getAbsolutePaths(buildFile, module.getSourceFiles()).map(localFileSystem::findFileByPath)
val ktFiles = environment.getSourceFiles().filter { file -> file.virtualFile in moduleSourceFiles }
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
@@ -184,7 +172,11 @@ object KotlinToJVMBytecodeCompiler {
internal fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List<Module>, buildFile: File) {
for (module in chunk) {
configuration.addKotlinSourceRoots(getAbsoluteFiles(buildFile, module).map(File::getPath))
val commonSources = getAbsolutePaths(buildFile, module.getCommonSourceFiles()).toSet()
for (path in getAbsolutePaths(buildFile, module.getSourceFiles())) {
configuration.addKotlinSourceRoot(path, isCommon = path in commonSources)
}
}
for (module in chunk) {
@@ -224,6 +216,11 @@ object KotlinToJVMBytecodeCompiler {
configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
}
private fun getAbsolutePaths(buildFile: File, sourceFilePaths: List<String>): List<String> =
sourceFilePaths.map { path ->
(File(path).takeIf(File::isAbsolute) ?: buildFile.resolveSibling(path)).absolutePath
}
private fun findMainClass(generationState: GenerationState, files: List<KtFile>): FqName? {
val mainFunctionDetector = MainFunctionDetector(generationState.bindingContext)
return files.asSequence()

View File

@@ -60,7 +60,7 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
for (arg in arguments.freeArgs) {
configuration.addKotlinSourceRoot(arg)
configuration.addKotlinSourceRoot(arg, isCommon = true)
}
if (arguments.classpath != null) {
configuration.addJvmClasspathRoots(arguments.classpath!!.split(File.pathSeparatorChar).map(::File))

View File

@@ -23,7 +23,9 @@ class IncrementalModuleInfo(
val projectRoot: File,
val dirToModule: Map<File, IncrementalModuleEntry>,
val nameToModules: Map<String, Set<IncrementalModuleEntry>>,
val jarToClassListFile: Map<File, File>
val jarToClassListFile: Map<File, File>,
// only for js
val jarToModule: Map<File, IncrementalModuleEntry>
) : Serializable {
companion object {
private const val serialVersionUID = 0L

View File

@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.cli.js.K2JSCompiler
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.daemon.report.CompileServicesFacadeMessageCollector
@@ -50,9 +49,10 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryAndroid
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJs
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJvm
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
@@ -475,8 +475,14 @@ class CompileServiceImpl(
incrementalCompilationOptions.customCacheVersionFileName,
workingDir,
enabled = true)
val compiler = IncrementalJsCompilerRunner(workingDir, versions, reporter)
val modulesApiHistory = ModulesApiHistoryJs(incrementalCompilationOptions.modulesInfo)
val compiler = IncrementalJsCompilerRunner(
workingDir = workingDir,
cacheVersions = versions,
reporter = reporter,
buildHistoryFile = incrementalCompilationOptions.multiModuleICSettings.buildHistoryFile,
modulesApiHistory = modulesApiHistory
)
return compiler.compile(allKotlinFiles, args, compilerMessageCollector, changedFiles)
}
@@ -509,6 +515,8 @@ class CompileServiceImpl(
it.getJavaSourceRoots().map { JvmSourceRoot(File(it.path), it.packagePrefix) }
}
k2jvmArgs.commonSources = parsedModule.modules.flatMap { it.getCommonSourceFiles() }.toTypedArray().takeUnless { it.isEmpty() }
val allKotlinFiles = parsedModule.modules.flatMap { it.getSourceFiles().map(::File) }
k2jvmArgs.friendPaths = parsedModule.modules.flatMap(Module::getFriendPaths).toTypedArray()

View File

@@ -33,7 +33,10 @@ class IncrementalPackagePartProvider(
private val moduleMappings = storageManager.createLazyValue {
incrementalCaches.map { cache ->
ModuleMapping.loadModuleMapping(cache.getModuleMappingData(), "<incremental>", deserializationConfiguration)
ModuleMapping.loadModuleMapping(cache.getModuleMappingData(), "<incremental>", deserializationConfiguration) { version ->
// Incremental compilation should fall back to full rebuild if the minor component of the metadata version has changed
throw IllegalStateException("Version of the generated module should not be incompatible: $version")
}
}
}

View File

@@ -632,6 +632,7 @@ public interface Errors {
DiagnosticFactory0<PsiElement> OPTIONAL_EXPECTATION_NOT_ON_EXPECTED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE = DiagnosticFactory0.create(ERROR);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -289,6 +289,7 @@ public class DefaultErrorMessages {
MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class");
MAP.put(OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, "Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry");
MAP.put(OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE, "Declaration annotated with '@OptionalExpectation' can only be used in common module sources");
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");

View File

@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.resolve.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
@@ -16,5 +18,10 @@ class OptionalExpectationUsageChecker : ClassifierUsageChecker {
if (!element.isUsageAsAnnotationOrImport()) {
context.trace.report(Errors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY.on(element))
}
val ktFile = element.containingFile as KtFile
if (ktFile.isCommonSource != true) {
context.trace.report(Errors.OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE.on(element))
}
}
}

View File

@@ -0,0 +1,16 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.multiplatform
import com.intellij.openapi.util.Key
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.UserDataProperty
/**
* Returns true if this file is a part of the common module in a multi-platform project.
* This setting only makes sense in the compiler, not in the IDE where sources from common modules are analyzed as common
*/
var KtFile.isCommonSource: Boolean? by UserDataProperty(Key.create("IS_COMMON_SOURCE"))

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.name.FqName
import java.io.File
class DirtyFilesContainer(
private val caches: IncrementalCachesManager<*>,
private val reporter: ICReporter
) {
private val myDirtyFiles = HashSet<File>()
fun toMutableList(): MutableList<File> =
ArrayList(myDirtyFiles)
fun add(files: Iterable<File>) {
val existingKotlinFiles = files.filter { it.isKotlinFile() }
if (existingKotlinFiles.isNotEmpty()) {
myDirtyFiles.addAll(existingKotlinFiles)
}
}
fun addByDirtySymbols(lookupSymbols: Collection<LookupSymbol>) {
if (lookupSymbols.isEmpty()) return
val dirtyFilesFromLookups = mapLookupSymbolsToFiles(caches.lookupCache, lookupSymbols, reporter)
add(dirtyFilesFromLookups)
}
fun addByDirtyClasses(dirtyClassesFqNames: Collection<FqName>) {
if (dirtyClassesFqNames.isEmpty()) return
val fqNamesWithSubtypes = dirtyClassesFqNames.flatMap {
withSubtypes(
it,
listOf(caches.platformCache)
)
}
val dirtyFilesFromFqNames =
mapClassesFqNamesToFiles(listOf(caches.platformCache), fqNamesWithSubtypes, reporter)
add(dirtyFilesFromFqNames)
}
}

View File

@@ -41,6 +41,7 @@ abstract class IncrementalCompilerRunner<
cacheDirName: String,
protected val cacheVersions: List<CacheVersion>,
protected val reporter: ICReporter,
private val buildHistoryFile: File,
private val localStateDirs: Collection<File> = emptyList()
) {
@@ -117,11 +118,9 @@ abstract class IncrementalCompilerRunner<
protected abstract fun calculateSourcesToCompile(caches: CacheManager, changedFiles: ChangedFiles.Known, args: Args): CompilationMode
protected fun getDirtyFiles(changedFiles: ChangedFiles.Known): HashSet<File> {
val dirtyFiles = HashSet<File>(with(changedFiles) { modified.size + removed.size })
with(changedFiles) {
modified.asSequence() + removed.asSequence()
}.filterTo(dirtyFiles, File::isKotlinFile)
protected fun initDirtyFiles(dirtyFiles: DirtyFilesContainer, changedFiles: ChangedFiles.Known) {
dirtyFiles.add(changedFiles.modified)
dirtyFiles.add(changedFiles.removed)
if (dirtySourcesSinceLastTimeFile.exists()) {
val files = dirtySourcesSinceLastTimeFile.readLines().map(::File)
@@ -129,14 +128,12 @@ abstract class IncrementalCompilerRunner<
reporter.report { "Source files added since last compilation: ${reporter.pathsAsString(files)}" }
}
dirtyFiles.addAll(files)
dirtyFiles.add(files)
}
return dirtyFiles
}
protected sealed class CompilationMode {
class Incremental(val dirtyFiles: Set<File>) : CompilationMode()
class Incremental(val dirtyFiles: DirtyFilesContainer) : CompilationMode()
class Rebuild(getReason: () -> String = { "" }) : CompilationMode() {
val reason: String by lazy(getReason)
}
@@ -188,7 +185,7 @@ abstract class IncrementalCompilerRunner<
preBuildHook(args, compilationMode)
val dirtySources = when (compilationMode) {
is CompilationMode.Incremental -> ArrayList(compilationMode.dirtyFiles)
is CompilationMode.Incremental -> compilationMode.dirtyFiles.toMutableList()
is CompilationMode.Rebuild -> allKotlinSources.toMutableList()
}
@@ -303,11 +300,20 @@ abstract class IncrementalCompilerRunner<
open fun runWithNoDirtyKotlinSources(caches: CacheManager): Boolean = false
protected open fun processChangesAfterBuild(
private fun processChangesAfterBuild(
compilationMode: CompilationMode,
currentBuildInfo: BuildInfo,
dirtyData: DirtyData
) {
val prevDiffs = BuildDiffsStorage.readFromFile(buildHistoryFile, reporter)?.buildDiffs ?: emptyList()
val newDiff = if (compilationMode is CompilationMode.Incremental) {
BuildDifference(currentBuildInfo.startTS, true, dirtyData)
} else {
val emptyDirtyData = DirtyData()
BuildDifference(currentBuildInfo.startTS, false, emptyDirtyData)
}
BuildDiffsStorage.writeToFile(buildHistoryFile, BuildDiffsStorage(prevDiffs + newDiff), reporter)
}
companion object {

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.incremental
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
@@ -27,7 +26,8 @@ import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory
import java.io.File
fun makeJsIncrementally(
@@ -41,9 +41,13 @@ fun makeJsIncrementally(
val versions = commonCacheVersions(cachesDir, isIncremental) + standaloneCacheVersion(cachesDir, isIncremental)
val allKotlinFiles = sourceRoots.asSequence().flatMap { it.walk() }
.filter { it.isFile && it.extension.equals("kt", ignoreCase = true) }.toList()
val buildHistoryFile = File(cachesDir, "build-history.bin")
withJsIC {
val compiler = IncrementalJsCompilerRunner(cachesDir, versions, reporter)
val compiler = IncrementalJsCompilerRunner(
cachesDir, versions, reporter,
buildHistoryFile = buildHistoryFile,
modulesApiHistory = EmptyModulesApiHistory)
compiler.compile(allKotlinFiles, args, messageCollector, providedChangedFiles = null)
}
}
@@ -62,12 +66,15 @@ inline fun <R> withJsIC(fn: () -> R): R {
class IncrementalJsCompilerRunner(
workingDir: File,
cacheVersions: List<CacheVersion>,
reporter: ICReporter
reporter: ICReporter,
buildHistoryFile: File,
private val modulesApiHistory: ModulesApiHistory
) : IncrementalCompilerRunner<K2JSCompilerArguments, IncrementalJsCachesManager>(
workingDir,
"caches-js",
cacheVersions,
reporter
reporter,
buildHistoryFile = buildHistoryFile
) {
override fun isICEnabled(): Boolean =
IncrementalCompilation.isEnabledForJs()
@@ -79,39 +86,31 @@ class IncrementalJsCompilerRunner(
File(args.outputFile).parentFile
override fun calculateSourcesToCompile(caches: IncrementalJsCachesManager, changedFiles: ChangedFiles.Known, args: K2JSCompilerArguments): CompilationMode {
if (BuildInfo.read(lastBuildInfoFile) == null) return CompilationMode.Rebuild { "No information on previous build" }
val lastBuildInfo = BuildInfo.read(lastBuildInfoFile)
?: return CompilationMode.Rebuild { "No information on previous build" }
val libs = (args.libraries ?: "").split(File.pathSeparator).mapTo(HashSet()) { File(it) }
val libsDirs = libs.filter { it.isDirectory }
val dirtyFiles = DirtyFilesContainer(caches, reporter)
initDirtyFiles(dirtyFiles, changedFiles)
val changedLib = changedFiles.allAsSequence.find { it in libs }
?: changedFiles.allAsSequence.find { changedFile ->
libsDirs.any { libDir -> FileUtil.isAncestor(libDir, changedFile, true) }
}
val libs = (args.libraries ?: "").split(File.pathSeparator).map { File(it) }
val classpathChanges = getClasspathChanges(libs, changedFiles, lastBuildInfo, modulesApiHistory, reporter)
if (changedLib != null) return CompilationMode.Rebuild { "Library has been changed: $changedLib" }
val dirtyFiles = getDirtyFiles(changedFiles)
// todo: unify with JVM calculateSourcesToCompile
fun markDirtyBy(lookupSymbols: Collection<LookupSymbol>) {
if (lookupSymbols.isEmpty()) return
val dirtyFilesFromLookups = mapLookupSymbolsToFiles(caches.lookupCache, lookupSymbols, reporter)
dirtyFiles.addAll(dirtyFilesFromLookups)
@Suppress("UNUSED_VARIABLE") // for sealed when
val unused = when (classpathChanges) {
is ChangesEither.Unknown -> return CompilationMode.Rebuild {
// todo: we can recompile all files incrementally (not cleaning caches), so rebuild won't propagate
"Could not get classpath's changes${classpathChanges.reason?.let { ": $it" }}"
}
is ChangesEither.Known -> {
dirtyFiles.addByDirtySymbols(classpathChanges.lookupSymbols)
dirtyFiles.addByDirtyClasses(classpathChanges.fqNames)
}
}
fun markDirtyBy(dirtyClassesFqNames: Collection<FqName>) {
if (dirtyClassesFqNames.isEmpty()) return
val fqNamesWithSubtypes = dirtyClassesFqNames.flatMap { withSubtypes(it, listOf(caches.platformCache)) }
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.platformCache), fqNamesWithSubtypes, reporter)
dirtyFiles.addAll(dirtyFilesFromFqNames)
}
val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles)
markDirtyBy(removedClassesChanges.dirtyLookupSymbols)
markDirtyBy(removedClassesChanges.dirtyClassesFqNames)
dirtyFiles.addByDirtySymbols(removedClassesChanges.dirtyLookupSymbols)
dirtyFiles.addByDirtyClasses(removedClassesChanges.dirtyClassesFqNames)
return CompilationMode.Incremental(dirtyFiles)
}

View File

@@ -104,7 +104,7 @@ class IncrementalJvmCompilerRunner(
cacheVersions: List<CacheVersion>,
reporter: ICReporter,
private val usePreciseJavaTracking: Boolean,
private val buildHistoryFile: File,
buildHistoryFile: File,
localStateDirs: Collection<File>,
private val modulesApiHistory: ModulesApiHistory
) : IncrementalCompilerRunner<K2JVMCompilerArguments, IncrementalJvmCachesManager>(
@@ -112,7 +112,8 @@ class IncrementalJvmCompilerRunner(
"caches-jvm",
cacheVersions,
reporter,
localStateDirs = localStateDirs
localStateDirs = localStateDirs,
buildHistoryFile = buildHistoryFile
) {
override fun isICEnabled(): Boolean =
IncrementalCompilation.isEnabledForJvm()
@@ -144,27 +145,13 @@ class IncrementalJvmCompilerRunner(
changedFiles: ChangedFiles.Known,
args: K2JVMCompilerArguments
): CompilationMode {
val dirtyFiles = getDirtyFiles(changedFiles)
fun markDirtyBy(lookupSymbols: Collection<LookupSymbol>) {
if (lookupSymbols.isEmpty()) return
val dirtyFilesFromLookups = mapLookupSymbolsToFiles(caches.lookupCache, lookupSymbols, reporter)
dirtyFiles.addAll(dirtyFilesFromLookups)
}
fun markDirtyBy(dirtyClassesFqNames: Collection<FqName>) {
if (dirtyClassesFqNames.isEmpty()) return
val fqNamesWithSubtypes = dirtyClassesFqNames.flatMap { withSubtypes(it, listOf(caches.platformCache)) }
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.platformCache), fqNamesWithSubtypes, reporter)
dirtyFiles.addAll(dirtyFilesFromFqNames)
}
val dirtyFiles = DirtyFilesContainer(caches, reporter)
initDirtyFiles(dirtyFiles, changedFiles)
val lastBuildInfo = BuildInfo.read(lastBuildInfoFile) ?: return CompilationMode.Rebuild { "No information on previous build" }
reporter.report { "Last Kotlin Build info -- $lastBuildInfo" }
val classpathChanges = getClasspathChanges(args.classpathAsList, changedFiles, lastBuildInfo)
val classpathChanges = getClasspathChanges(args.classpathAsList, changedFiles, lastBuildInfo, modulesApiHistory, reporter)
@Suppress("UNUSED_VARIABLE") // for sealed when
val unused = when (classpathChanges) {
@@ -173,8 +160,8 @@ class IncrementalJvmCompilerRunner(
"Could not get classpath's changes${classpathChanges.reason?.let { ": $it" }}"
}
is ChangesEither.Known -> {
markDirtyBy(classpathChanges.lookupSymbols)
markDirtyBy(classpathChanges.fqNames)
dirtyFiles.addByDirtySymbols(classpathChanges.lookupSymbols)
dirtyFiles.addByDirtyClasses(classpathChanges.fqNames)
}
}
@@ -184,9 +171,8 @@ class IncrementalJvmCompilerRunner(
is ChangesEither.Known -> javaFilesChanges.lookupSymbols
is ChangesEither.Unknown -> return CompilationMode.Rebuild { "Could not get changes for java files" }
}
markDirtyBy(affectedJavaSymbols)
}
else {
dirtyFiles.addByDirtySymbols(affectedJavaSymbols)
} else {
if (!processChangedJava(changedFiles, caches)) {
return CompilationMode.Rebuild { "Could not get changes for java files" }
}
@@ -195,9 +181,9 @@ class IncrementalJvmCompilerRunner(
val androidLayoutChanges = processLookupSymbolsForAndroidLayouts(changedFiles)
val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles)
markDirtyBy(androidLayoutChanges)
markDirtyBy(removedClassesChanges.dirtyLookupSymbols)
markDirtyBy(removedClassesChanges.dirtyClassesFqNames)
dirtyFiles.addByDirtySymbols(androidLayoutChanges)
dirtyFiles.addByDirtySymbols(removedClassesChanges.dirtyLookupSymbols)
dirtyFiles.addByDirtyClasses(removedClassesChanges.dirtyClassesFqNames)
return CompilationMode.Incremental(dirtyFiles)
}
@@ -257,58 +243,6 @@ class IncrementalJvmCompilerRunner(
return result
}
private fun getClasspathChanges(
classpath: List<File>,
changedFiles: ChangedFiles.Known,
lastBuildInfo: BuildInfo
): ChangesEither {
val classpathSet = HashSet<File>()
for (file in classpath) {
when {
file.isFile -> classpathSet.add(file)
file.isDirectory -> file.walk().filterTo(classpathSet) { it.isFile }
}
}
val modifiedClasspath = changedFiles.modified.filterTo(HashSet()) { it in classpathSet }
val removedClasspath = changedFiles.removed.filterTo(HashSet()) { it in classpathSet }
// todo: removed classes could be processed normally
if (removedClasspath.isNotEmpty()) return ChangesEither.Unknown("Some files are removed from classpath $removedClasspath")
if (modifiedClasspath.isEmpty()) return ChangesEither.Known()
val lastBuildTS = lastBuildInfo.startTS
val symbols = HashSet<LookupSymbol>()
val fqNames = HashSet<FqName>()
val historyFilesEither = modulesApiHistory.historyFilesForChangedFiles(modifiedClasspath)
val historyFiles = when (historyFilesEither) {
is Either.Success<Set<File>> -> historyFilesEither.value
is Either.Error -> return ChangesEither.Unknown(historyFilesEither.reason)
}
for (historyFile in historyFiles) {
val allBuilds = BuildDiffsStorage.readDiffsFromFile(historyFile, reporter = reporter)
?: return ChangesEither.Unknown("Could not read diffs from $historyFile")
val (knownBuilds, newBuilds) = allBuilds.partition { it.ts <= lastBuildTS }
if (knownBuilds.isEmpty()) {
return ChangesEither.Unknown("No previously known builds for $historyFile")
}
for (buildDiff in newBuilds) {
if (!buildDiff.isIncremental) return ChangesEither.Unknown("Non-incremental build from dependency $historyFile")
val dirtyData = buildDiff.dirtyData
symbols.addAll(dirtyData.dirtyLookupSymbols)
fqNames.addAll(dirtyData.dirtyClassesFqNames)
}
}
return ChangesEither.Known(symbols, fqNames)
}
override fun preBuildHook(args: K2JVMCompilerArguments, compilationMode: CompilationMode) {
if (compilationMode is CompilationMode.Incremental) {
val destinationDir = args.destinationAsFile
@@ -377,22 +311,6 @@ class IncrementalJvmCompilerRunner(
override fun additionalDirtyLookupSymbols(): Iterable<LookupSymbol> =
javaFilesProcessor?.allChangedSymbols ?: emptyList()
override fun processChangesAfterBuild(
compilationMode: CompilationMode,
currentBuildInfo: BuildInfo,
dirtyData: DirtyData
) {
val prevDiffs = BuildDiffsStorage.readFromFile(buildHistoryFile, reporter)?.buildDiffs ?: emptyList()
val newDiff = if (compilationMode is CompilationMode.Incremental) {
BuildDifference(currentBuildInfo.startTS, true, dirtyData)
} else {
val emptyDirtyData = DirtyData()
BuildDifference(currentBuildInfo.startTS, false, emptyDirtyData)
}
BuildDiffsStorage.writeToFile(buildHistoryFile, BuildDiffsStorage(prevDiffs + newDiff), reporter)
}
override fun makeServices(
args: K2JVMCompilerArguments,
lookupTracker: LookupTracker,
@@ -422,13 +340,16 @@ class IncrementalJvmCompilerRunner(
val compiler = K2JVMCompiler()
val outputDir = args.destinationAsFile
val classpath = args.classpathAsList
val moduleFile = makeModuleFile(args.moduleName!!,
isTest = false,
outputDir = outputDir,
sourcesToCompile = sourcesToCompile,
javaSourceRoots = javaSourceRoots,
classpath = classpath,
friendDirs = listOf())
val moduleFile = makeModuleFile(
args.moduleName!!,
isTest = false,
outputDir = outputDir,
sourcesToCompile = sourcesToCompile,
commonSources = args.commonSources?.map(::File).orEmpty(),
javaSourceRoots = javaSourceRoots,
classpath = classpath,
friendDirs = listOf()
)
val destination = args.destination
args.destination = null
args.buildFile = moduleFile.absolutePath

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory
import org.jetbrains.kotlin.incremental.util.Either
import org.jetbrains.kotlin.name.FqName
import java.io.File
internal fun getClasspathChanges(
classpath: List<File>,
changedFiles: ChangedFiles.Known,
lastBuildInfo: BuildInfo,
modulesApiHistory: ModulesApiHistory,
reporter: ICReporter?
): ChangesEither {
val classpathSet = HashSet<File>()
for (file in classpath) {
when {
file.isFile -> classpathSet.add(file)
file.isDirectory -> file.walk().filterTo(classpathSet) { it.isFile }
}
}
val modifiedClasspath = changedFiles.modified.filterTo(HashSet()) { it in classpathSet }
val removedClasspath = changedFiles.removed.filterTo(HashSet()) { it in classpathSet }
// todo: removed classes could be processed normally
if (removedClasspath.isNotEmpty()) return ChangesEither.Unknown("Some files are removed from classpath $removedClasspath")
if (modifiedClasspath.isEmpty()) return ChangesEither.Known()
val lastBuildTS = lastBuildInfo.startTS
val symbols = HashSet<LookupSymbol>()
val fqNames = HashSet<FqName>()
val historyFilesEither = modulesApiHistory.historyFilesForChangedFiles(modifiedClasspath)
val historyFiles = when (historyFilesEither) {
is Either.Success<Set<File>> -> historyFilesEither.value
is Either.Error -> return ChangesEither.Unknown(historyFilesEither.reason)
}
for (historyFile in historyFiles) {
val allBuilds = BuildDiffsStorage.readDiffsFromFile(historyFile, reporter = reporter)
?: return ChangesEither.Unknown("Could not read diffs from $historyFile")
val (knownBuilds, newBuilds) = allBuilds.partition { it.ts <= lastBuildTS }
if (knownBuilds.isEmpty()) {
return ChangesEither.Unknown("No previously known builds for $historyFile")
}
for (buildDiff in newBuilds) {
if (!buildDiff.isIncremental) return ChangesEither.Unknown("Non-incremental build from dependency $historyFile")
val dirtyData = buildDiff.dirtyData
symbols.addAll(dirtyData.dirtyLookupSymbols)
fqNames.addAll(dirtyData.dirtyClassesFqNames)
}
}
return ChangesEither.Known(symbols, fqNames)
}

View File

@@ -22,7 +22,7 @@ object EmptyModulesApiHistory : ModulesApiHistory {
Either.Error("Multi-module IC is not configured")
}
open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo) : ModulesApiHistory {
abstract class ModulesApiHistoryBase(protected val modulesInfo: IncrementalModuleInfo) : ModulesApiHistory {
protected val projectRootPath: Path = Paths.get(modulesInfo.projectRoot.absolutePath)
private val dirToHistoryFileCache = HashMap<File, Set<File>>()
@@ -86,7 +86,11 @@ open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo
return Either.Success(history)
}
protected open fun getBuildHistoryFilesForJar(jar: File): Either<Set<File>> {
protected abstract fun getBuildHistoryFilesForJar(jar: File): Either<Set<File>>
}
class ModulesApiHistoryJvm(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryBase(modulesInfo) {
override fun getBuildHistoryFilesForJar(jar: File): Either<Set<File>> {
val classListFile = modulesInfo.jarToClassListFile[jar] ?: return Either.Error("Unknown jar: $jar")
if (!classListFile.isFile) return Either.Error("Class list file does not exist $classListFile")
@@ -109,7 +113,18 @@ open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo
}
}
class ModulesApiHistoryAndroid(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryJvm(modulesInfo) {
class ModulesApiHistoryJs(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryBase(modulesInfo) {
override fun getBuildHistoryFilesForJar(jar: File): Either<Set<File>> {
val moduleEntry = modulesInfo.jarToModule[jar]
return when {
moduleEntry != null -> Either.Success(setOf(moduleEntry.buildHistoryFile))
else -> Either.Error("No module is found for jar $jar")
}
}
}
class ModulesApiHistoryAndroid(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryBase(modulesInfo) {
private val delegate = ModulesApiHistoryJvm(modulesInfo)
override fun historyFilesForChangedFiles(changedFiles: Set<File>): Either<Set<File>> {

View File

@@ -361,6 +361,11 @@ public class IncrementalJsCompilerRunnerTestGenerated extends AbstractIncrementa
runTest("jps-plugin/testData/incremental/pureKotlin/ourClassReferenced/");
}
@TestMetadata("overloadInlined")
public void testOverloadInlined() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/overloadInlined/");
}
@TestMetadata("packageConstantChanged")
public void testPackageConstantChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/packageConstantChanged/");
@@ -551,6 +556,11 @@ public class IncrementalJsCompilerRunnerTestGenerated extends AbstractIncrementa
runTest("jps-plugin/testData/incremental/pureKotlin/returnTypeChanged/");
}
@TestMetadata("secondaryConstructorInlined")
public void testSecondaryConstructorInlined() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/secondaryConstructorInlined/");
}
@TestMetadata("simpleClassDependency")
public void testSimpleClassDependency() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/simpleClassDependency/");

View File

@@ -361,6 +361,11 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement
runTest("jps-plugin/testData/incremental/pureKotlin/ourClassReferenced/");
}
@TestMetadata("overloadInlined")
public void testOverloadInlined() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/overloadInlined/");
}
@TestMetadata("packageConstantChanged")
public void testPackageConstantChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/packageConstantChanged/");
@@ -551,6 +556,11 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement
runTest("jps-plugin/testData/incremental/pureKotlin/returnTypeChanged/");
}
@TestMetadata("secondaryConstructorInlined")
public void testSecondaryConstructorInlined() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/secondaryConstructorInlined/");
}
@TestMetadata("simpleClassDependency")
public void testSimpleClassDependency() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/simpleClassDependency/");

View File

@@ -58,7 +58,8 @@ class ModulesApiHistoryAndroidTest {
projectRoot = projectRoot,
dirToModule = mapOf(appKotlinDestination to appEntry, libKotlinDestination to libEntry),
nameToModules = mapOf("app" to setOf(appEntry), "lib" to setOf(libEntry)),
jarToClassListFile = mapOf()
jarToClassListFile = mapOf(),
jarToModule = mapOf()
)
androidHistory = ModulesApiHistoryAndroid(info)

View File

@@ -4,6 +4,8 @@ where advanced options include:
-Xfriend-modules-disabled Disable internal declaration export
-Xtyped-arrays Translate primitive arrays to JS typed arrays
-Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info
-Xcommon-sources=<path> Sources of the common module that need to be compiled together with this module in the multi-platform mode.
Should be a subset of sources passed as free arguments
-Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
-Xdump-perf=<path> Dump detailed performance statistics to the specified file

View File

@@ -60,6 +60,8 @@ where advanced options include:
-Xuse-old-class-files-reading Use old class files reading implementation (may slow down the build and should be used in case of problems with the new implementation)
-Xuse-type-table Use type table in metadata serialization
-Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info
-Xcommon-sources=<path> Sources of the common module that need to be compiled together with this module in the multi-platform mode.
Should be a subset of sources passed as free arguments
-Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
-Xdump-perf=<path> Dump detailed performance statistics to the specified file

View File

@@ -1,4 +1,5 @@
error: incompatible classes were found in dependencies. Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors
compiler/testData/cli/jvm/wrongAbiVersionLib/bin/META-INF/main.kotlin_module: error: module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 0.30.0, expected version is $ABI_VERSION$.
compiler/testData/cli/jvm/wrongAbiVersion.kt:3:12: error: class 'ClassWithWrongAbiVersion' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 0.30.0, expected version is $ABI_VERSION$.
The class is loaded from $TESTDATA_DIR$/wrongAbiVersionLib/bin/ClassWithWrongAbiVersion.class
fun foo(x: ClassWithWrongAbiVersion) {
@@ -10,4 +11,4 @@ compiler/testData/cli/jvm/wrongAbiVersion.kt:6:7: error: unresolved reference. N
public fun String.replaceIndent(newIndent: String = ...): String defined in kotlin.text
1.replaceIndent(2, 3)
^
COMPILATION_ERROR
COMPILATION_ERROR

View File

@@ -1,5 +0,0 @@
$TESTDATA_DIR$/wrongAbiVersionNoErrors.kt
-classpath
$TESTDATA_DIR$/wrongAbiVersionLib/bin
-d
$TEMP_DIR$

View File

@@ -1,7 +0,0 @@
// This should not compile because there are usages of symbols with the wrong ABI version!
import wrong.ClassWithInnerLambda
fun happy(): Int {
return 2 + 2
}

View File

@@ -1,6 +0,0 @@
error: incompatible classes were found in dependencies. Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors
compiler/testData/cli/jvm/wrongAbiVersionNoErrors.kt:3:14: error: class 'wrong.ClassWithInnerLambda' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 0.30.0, expected version is $ABI_VERSION$.
The class is loaded from $TESTDATA_DIR$/wrongAbiVersionLib/bin/wrong/ClassWithInnerLambda.class
import wrong.ClassWithInnerLambda
^
COMPILATION_ERROR

View File

@@ -23,6 +23,8 @@ actual annotation class A(actual val x: Int)
// MODULE: main(library)
// FILE: main.kt
@file:Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // TODO: support common sources in the test infrastructure
package usage
import a.A

View File

@@ -9,6 +9,8 @@ expect annotation class Anno(val s: String)
// FILE: jvm.kt
@file:Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // TODO: support common sources in the test infrastructure
import java.lang.reflect.AnnotatedElement
@Anno("Foo")

View File

@@ -3,6 +3,8 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@file:Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // TODO: support common sources in the test infrastructure
@OptionalExpectation
expect annotation class Anno(val s: String)

View File

@@ -1,4 +1,5 @@
error: incompatible classes were found in dependencies. Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors
$TMP_DIR$/library-after.jar!/META-INF/main.kotlin_module: error: module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 42.0.0, expected version is $ABI_VERSION$.
compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersion/source.kt:5:16: error: class 'a.A' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 42.0.0, expected version is $ABI_VERSION$.
The class is loaded from $TMP_DIR$/library-after.jar!/a/A.class
fun baz(param: A, nested: A.Nested) {

View File

@@ -1,3 +1,4 @@
$TMP_DIR$/library-after.jar!/META-INF/main.kotlin_module: error: module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 42.0.0, expected version is $ABI_VERSION$.
compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionBadMetadata/source.kt:12:13: error: unresolved reference: foo
val x = foo()
^
@@ -10,4 +11,4 @@ compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionBadMeta
compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionBadMetadata/source.kt:15:12: error: unresolved reference: TA
val z: TA = ""
^
COMPILATION_ERROR
COMPILATION_ERROR

View File

@@ -1,3 +1,4 @@
$TMP_DIR$/library-after.jar!/META-INF/main.kotlin_module: error: module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 42.0.0, expected version is $ABI_VERSION$.
compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionBadMetadata2/source.kt:12:13: error: unresolved reference: foo
val x = foo()
^
@@ -10,4 +11,4 @@ compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionBadMeta
compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionBadMetadata2/source.kt:15:12: error: unresolved reference: TA
val z: TA = ""
^
COMPILATION_ERROR
COMPILATION_ERROR

View File

@@ -14,6 +14,9 @@ expect annotation class B(val s: String)
actual annotation class A(actual val x: Int)
// FILE: B.kt
@file:Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // TODO: support common sources in the test infrastructure
import a.A
import a.B
import java.lang.reflect.Modifier

View File

@@ -39,11 +39,20 @@ compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:19:20:
@InOtherAnnotation(A())
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:1:24: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
fun useInReturnType(): A? = null
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:1:24: error: declaration annotated with '@OptionalExpectation' can only be used in common module sources
fun useInReturnType(): A? = null
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:3:43: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
annotation class AnotherAnnotation(val a: A)
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:3:43: error: declaration annotated with '@OptionalExpectation' can only be used in common module sources
annotation class AnotherAnnotation(val a: A)
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:5:20: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
@AnotherAnnotation(A())
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:5:20: error: declaration annotated with '@OptionalExpectation' can only be used in common module sources
@AnotherAnnotation(A())
^

View File

@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
import org.jetbrains.kotlin.cli.common.config.ContentRootsKt;
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
@@ -610,11 +611,11 @@ public class KotlinTestUtils {
}
public static void resolveAllKotlinFiles(KotlinCoreEnvironment environment) throws IOException {
List<String> paths = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (paths.isEmpty()) return;
List<KotlinSourceRoot> roots = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (roots.isEmpty()) return;
List<KtFile> ktFiles = new ArrayList<>();
for (String path : paths) {
File file = new File(path);
for (KotlinSourceRoot root : roots) {
File file = new File(root.getPath());
if (file.isFile()) {
ktFiles.add(loadJetFile(environment.getProject(), file));
}

View File

@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
import org.jetbrains.kotlin.cli.common.config.ContentRootsKt;
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
@@ -609,11 +610,11 @@ public class KotlinTestUtils {
}
public static void resolveAllKotlinFiles(KotlinCoreEnvironment environment) throws IOException {
List<String> paths = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (paths.isEmpty()) return;
List<KotlinSourceRoot> roots = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (roots.isEmpty()) return;
List<KtFile> ktFiles = new ArrayList<>();
for (String path : paths) {
File file = new File(path);
for (KotlinSourceRoot root : roots) {
File file = new File(root.getPath());
if (file.isFile()) {
ktFiles.add(loadJetFile(environment.getProject(), file));
}

View File

@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
import org.jetbrains.kotlin.cli.common.config.ContentRootsKt;
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
@@ -609,11 +610,11 @@ public class KotlinTestUtils {
}
public static void resolveAllKotlinFiles(KotlinCoreEnvironment environment) throws IOException {
List<String> paths = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (paths.isEmpty()) return;
List<KotlinSourceRoot> roots = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (roots.isEmpty()) return;
List<KtFile> ktFiles = new ArrayList<>();
for (String path : paths) {
File file = new File(path);
for (KotlinSourceRoot root : roots) {
File file = new File(root.getPath());
if (file.isFile()) {
ktFiles.add(loadJetFile(environment.getProject(), file));
}

View File

@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
import org.jetbrains.kotlin.cli.common.config.ContentRootsKt;
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
@@ -609,11 +610,11 @@ public class KotlinTestUtils {
}
public static void resolveAllKotlinFiles(KotlinCoreEnvironment environment) throws IOException {
List<String> paths = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (paths.isEmpty()) return;
List<KotlinSourceRoot> roots = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
if (roots.isEmpty()) return;
List<KtFile> ktFiles = new ArrayList<>();
for (String path : paths) {
File file = new File(path);
for (KotlinSourceRoot root : roots) {
File file = new File(root.getPath());
if (file.isFile()) {
ktFiles.add(loadJetFile(environment.getProject(), file));
}

View File

@@ -586,11 +586,6 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/wrongAbiVersion.args");
}
@TestMetadata("wrongAbiVersionNoErrors.args")
public void testWrongAbiVersionNoErrors() throws Exception {
runTest("compiler/testData/cli/jvm/wrongAbiVersionNoErrors.args");
}
@TestMetadata("wrongArgument.args")
public void testWrongArgument() throws Exception {
runTest("compiler/testData/cli/jvm/wrongArgument.args");

View File

@@ -50,7 +50,8 @@ class JvmModuleProtoBufTest : KtUsefulTestCase() {
File(tmpdir, "META-INF/$moduleName.${ModuleMapping.MAPPING_FILE_EXT}").readBytes(), "test",
CompilerDeserializationConfiguration(
LanguageVersionSettingsImpl(loadWith, ApiVersion.createByLanguageVersion(loadWith))
)
),
::error
)
val result = buildString {
for (annotationClassId in mapping.moduleData.annotations) {

View File

@@ -55,24 +55,24 @@ abstract class AbstractMultiPlatformIntegrationTest : KtUsefulTestCase() {
val result = buildString {
appendln("-- Common --")
appendln(K2MetadataCompiler().compile(listOf(commonSrc), "-d", commonDest, *optionalStdlibCommon))
appendln(K2MetadataCompiler().compile(commonSrc, null, "-d", commonDest, *optionalStdlibCommon))
if (jvmSrc != null) {
appendln()
appendln("-- JVM --")
appendln(K2JVMCompiler().compileBothWays(commonSrc, jvmSrc, "-d", jvmDest!!))
appendln(K2JVMCompiler().compile(jvmSrc, commonSrc, "-d", jvmDest!!))
}
if (jsSrc != null) {
appendln()
appendln("-- JS --")
appendln(K2JSCompiler().compileBothWays(commonSrc, jsSrc, "-output", jsDest!!))
appendln(K2JSCompiler().compile(jsSrc, commonSrc, "-output", jsDest!!))
}
if (common2Src != null) {
appendln()
appendln("-- Common (2) --")
appendln(K2MetadataCompiler().compile(listOf(common2Src), "-d", common2Dest!!, "-cp", commonDest, *optionalStdlibCommon))
appendln(K2MetadataCompiler().compile(common2Src, null, "-d", common2Dest!!, "-cp", commonDest, *optionalStdlibCommon))
}
if (jvm2Src != null) {
@@ -80,7 +80,7 @@ abstract class AbstractMultiPlatformIntegrationTest : KtUsefulTestCase() {
appendln("-- JVM (2) --")
appendln(
K2JVMCompiler().compile(
listOf(jvm2Src), "-d", jvm2Dest!!,
jvm2Src, common2Src, "-d", jvm2Dest!!,
"-cp", listOfNotNull(commonDest, common2Dest, jvmDest).joinToString(File.pathSeparator)
)
)
@@ -100,28 +100,12 @@ abstract class AbstractMultiPlatformIntegrationTest : KtUsefulTestCase() {
}?.toFile() ?: error("kotlin-stdlib-common is not found in $stdlibCommonLibsDir")
}
private fun CLICompiler<*>.compileBothWays(commonSource: File, platformSource: File, vararg mainArguments: String): String {
val configurations = listOf(
listOf(platformSource, commonSource),
listOf(commonSource, platformSource)
)
val (platformFirst, commonFirst) = configurations.map { compile(it, *mainArguments) }
if (platformFirst != commonFirst) {
assertEquals(
"Compilation results are different when compiling [platform-specific, common] compared to when compiling [common, platform-specific]",
"// Compiling [platform-specific, common]\n\n$platformFirst",
"// Compiling [common, platform-specific]\n\n$commonFirst"
)
}
return platformFirst
}
private fun CLICompiler<*>.compile(sources: List<File>, vararg mainArguments: String): String = buildString {
private fun CLICompiler<*>.compile(sources: File, commonSources: File?, vararg mainArguments: String): String = buildString {
val (output, exitCode) = AbstractCliTest.executeCompilerGrabOutput(
this@compile,
sources.map(File::getAbsolutePath) + listOf("-Xmulti-platform") + mainArguments + loadExtraArguments(sources)
listOfNotNull(sources.absolutePath, commonSources?.absolutePath, commonSources?.absolutePath?.let("-Xcommon-sources="::plus)) +
"-Xmulti-platform" + mainArguments +
loadExtraArguments(listOfNotNull(sources, commonSources))
)
appendln("Exit code: $exitCode")
appendln("Output:")

View File

@@ -17,7 +17,7 @@ dependencies {
sourceSets {
"main" {
projectDefault()
resources.srcDir(File(rootDir, "resources")).apply { include("**") }
resources.srcDir(File(rootDir, "resources"))
}
"test" {}
}

View File

@@ -27,6 +27,8 @@ interface Module {
fun getSourceFiles(): List<String>
fun getCommonSourceFiles(): List<String>
fun getClasspathRoots(): List<String>
fun getJavaSourceRoots(): List<JavaRootPath>

View File

@@ -5,17 +5,20 @@
package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
fun ModuleMapping.Companion.loadModuleMapping(
bytes: ByteArray?,
debugName: String,
configuration: DeserializationConfiguration
configuration: DeserializationConfiguration,
reportIncompatibleVersionError: (JvmMetadataVersion) -> Unit
): ModuleMapping =
loadModuleMapping(
bytes,
debugName,
configuration.skipMetadataVersionCheck,
configuration.isJvmPackageNameSupported
configuration.isJvmPackageNameSupported,
reportIncompatibleVersionError
)

View File

@@ -18,6 +18,7 @@ package kotlin.reflect.jvm.internal.components
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.loadModuleMapping
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
@@ -45,11 +46,20 @@ class RuntimePackagePartProvider(private val classLoader: ClassLoader) : Package
for (resource in resources) {
try {
resource.openStream()?.use { stream ->
val mapping = ModuleMapping.loadModuleMapping(stream.readBytes(), resourcePath, DeserializationConfiguration.Default)
val mapping = ModuleMapping.loadModuleMapping(
stream.readBytes(), resourcePath, DeserializationConfiguration.Default
) { version ->
throw UnsupportedOperationException(
"Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is $version, " +
"expected version is ${JvmMetadataVersion.INSTANCE}. Please update Kotlin to the latest version"
)
}
for ((packageFqName, parts) in mapping.packageFqName2Parts) {
packageParts.getOrPut(packageFqName) { linkedSetOf() }.addAll(parts.parts)
}
}
} catch (e: UnsupportedOperationException) {
throw e
} catch (e: Exception) {
// TODO: do not swallow this exception?
}

View File

@@ -33,7 +33,8 @@ class ModuleMapping private constructor(
bytes: ByteArray?,
debugName: String,
skipMetadataVersionCheck: Boolean,
isJvmPackageNameSupported: Boolean
isJvmPackageNameSupported: Boolean,
reportIncompatibleVersionError: (JvmMetadataVersion) -> Unit
): ModuleMapping {
if (bytes == null) {
return EMPTY
@@ -47,47 +48,47 @@ class ModuleMapping private constructor(
return CORRUPTED
}
if (skipMetadataVersionCheck || JvmMetadataVersion(*versionNumber).isCompatible()) {
val moduleProto = JvmModuleProtoBuf.Module.parseFrom(stream) ?: return EMPTY
val result = linkedMapOf<String, PackageParts>()
for (proto in moduleProto.packagePartsList) {
val packageFqName = proto.packageFqName
val packageParts = result.getOrPut(packageFqName) { PackageParts(packageFqName) }
for ((index, partShortName) in proto.shortClassNameList.withIndex()) {
val multifileFacadeId = proto.multifileFacadeShortNameIdList.getOrNull(index)?.minus(1)
val facadeShortName = multifileFacadeId?.let(proto.multifileFacadeShortNameList::getOrNull)
val facadeInternalName = facadeShortName?.let { internalNameOf(packageFqName, it) }
packageParts.addPart(internalNameOf(packageFqName, partShortName), facadeInternalName)
}
if (isJvmPackageNameSupported) {
for ((index, partShortName) in proto.classWithJvmPackageNameShortNameList.withIndex()) {
val packageId = proto.classWithJvmPackageNamePackageIdList.getOrNull(index)
?: proto.classWithJvmPackageNamePackageIdList.lastOrNull()
?: continue
val jvmPackageName = moduleProto.jvmPackageNameList.getOrNull(packageId) ?: continue
packageParts.addPart(internalNameOf(jvmPackageName, partShortName), null)
}
}
}
for (proto in moduleProto.metadataPartsList) {
val packageParts = result.getOrPut(proto.packageFqName) { PackageParts(proto.packageFqName) }
proto.shortClassNameList.forEach(packageParts::addMetadataPart)
}
// TODO: read arguments of module annotations
val nameResolver = NameResolverImpl(moduleProto.stringTable, moduleProto.qualifiedNameTable)
val annotations = moduleProto.annotationList.map { proto -> nameResolver.getQualifiedClassName(proto.id) }
return ModuleMapping(result, BinaryModuleData(annotations), debugName)
} else {
// TODO: consider reporting "incompatible ABI version" error for package parts
val version = JvmMetadataVersion(*versionNumber)
if (!skipMetadataVersionCheck && !version.isCompatible()) {
reportIncompatibleVersionError(version)
return EMPTY
}
return EMPTY
val moduleProto = JvmModuleProtoBuf.Module.parseFrom(stream) ?: return EMPTY
val result = linkedMapOf<String, PackageParts>()
for (proto in moduleProto.packagePartsList) {
val packageFqName = proto.packageFqName
val packageParts = result.getOrPut(packageFqName) { PackageParts(packageFqName) }
for ((index, partShortName) in proto.shortClassNameList.withIndex()) {
val multifileFacadeId = proto.multifileFacadeShortNameIdList.getOrNull(index)?.minus(1)
val facadeShortName = multifileFacadeId?.let(proto.multifileFacadeShortNameList::getOrNull)
val facadeInternalName = facadeShortName?.let { internalNameOf(packageFqName, it) }
packageParts.addPart(internalNameOf(packageFqName, partShortName), facadeInternalName)
}
if (isJvmPackageNameSupported) {
for ((index, partShortName) in proto.classWithJvmPackageNameShortNameList.withIndex()) {
val packageId = proto.classWithJvmPackageNamePackageIdList.getOrNull(index)
?: proto.classWithJvmPackageNamePackageIdList.lastOrNull()
?: continue
val jvmPackageName = moduleProto.jvmPackageNameList.getOrNull(packageId) ?: continue
packageParts.addPart(internalNameOf(jvmPackageName, partShortName), null)
}
}
}
for (proto in moduleProto.metadataPartsList) {
val packageParts = result.getOrPut(proto.packageFqName) { PackageParts(proto.packageFqName) }
proto.shortClassNameList.forEach(packageParts::addMetadataPart)
}
// TODO: read arguments of module annotations
val nameResolver = NameResolverImpl(moduleProto.stringTable, moduleProto.qualifiedNameTable)
val annotations = moduleProto.annotationList.map { proto -> nameResolver.getQualifiedClassName(proto.id) }
return ModuleMapping(result, BinaryModuleData(annotations), debugName)
}
}
}

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea
import com.intellij.ide.IconProvider
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.IndexNotReadyException
import com.intellij.openapi.util.Iconable
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
@@ -52,7 +53,15 @@ class KotlinIconProvider : IconProvider(), DumbAware {
val result = psiElement.getBaseIcon()
if (flags and Iconable.ICON_FLAG_VISIBILITY > 0 && result != null && (psiElement is KtModifierListOwner && psiElement !is KtClassInitializer)) {
val list = psiElement.modifierList
return createRowIcon(result.addExpectActualMarker(psiElement), getVisibilityIcon(list))
val visibilityIcon = getVisibilityIcon(list)
val withExpectedActual: Icon = try {
result.addExpectActualMarker(psiElement)
} catch (indexNotReady: IndexNotReadyException) {
result
}
createRowIcon(withExpectedActual, visibilityIcon)
}
return result
}

View File

@@ -16,6 +16,7 @@ import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.util.ModificationTracker
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.ResolveScopeEnlarger
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValueProvider
import com.intellij.util.PathUtil
@@ -58,6 +59,14 @@ interface IdeaModuleInfo : org.jetbrains.kotlin.idea.caches.resolve.IdeaModuleIn
override fun dependencies(): List<IdeaModuleInfo>
}
private fun enlargedSearchScope(searchScope: GlobalSearchScope, moduleFile: VirtualFile?): GlobalSearchScope {
if (moduleFile == null) return searchScope
return ResolveScopeEnlarger.EP_NAME.extensions.fold(searchScope) { scope, enlarger ->
val extra = enlarger.getAdditionalResolveScope(moduleFile, scope.project)
if (extra != null) scope.union(extra) else scope
}
}
private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, forProduction: Boolean): List<IdeaModuleInfo> {
fun Module.toInfos() = correspondingModuleInfos().filter { !forProduction || it is ModuleProductionSourceInfo }
@@ -161,7 +170,7 @@ data class ModuleProductionSourceInfo internal constructor(
override val stableName: Name = module.getStableName()
override fun contentScope(): GlobalSearchScope = ModuleProductionSourceScope(module)
override fun contentScope(): GlobalSearchScope = enlargedSearchScope(ModuleProductionSourceScope(module), module.moduleFile)
override fun <T> createCachedValueProvider(f: () -> CachedValueProvider.Result<T>) = CachedValueProvider { f() }
}
@@ -177,7 +186,7 @@ data class ModuleTestSourceInfo internal constructor(override val module: Module
override val displayedName get() = module.name + " (test)"
override fun contentScope(): GlobalSearchScope = ModuleTestSourceScope(module)
override fun contentScope(): GlobalSearchScope = enlargedSearchScope(ModuleTestSourceScope(module), module.moduleFile)
override fun modulesWhoseInternalsAreVisible() = module.cached(CachedValueProvider {
val list = SmartList<ModuleInfo>()
@@ -433,4 +442,4 @@ data class PlatformModuleInfo(
}
fun IdeaModuleInfo.projectSourceModules(): List<ModuleSourceInfo>? =
(this as? ModuleSourceInfo)?.let(::listOf) ?: (this as? PlatformModuleInfo)?.containedModules
(this as? ModuleSourceInfo)?.let(::listOf) ?: (this as? PlatformModuleInfo)?.containedModules

View File

@@ -45,11 +45,13 @@ object KotlinJvmModuleAnnotationsIndex : FileBasedIndexExtension<String, List<Cl
override fun getIndexer(): DataIndexer<String, List<ClassId>, FileContent> = DataIndexer { inputData ->
val file = inputData.file
try {
val moduleMapping = ModuleMapping.loadModuleMapping(inputData.content, file.toString(), DeserializationConfiguration.Default)
return@DataIndexer mapOf(file.nameWithoutExtension to moduleMapping.moduleData.annotations.map(ClassId::fromString))
val moduleMapping = ModuleMapping.loadModuleMapping(inputData.content, file.toString(), DeserializationConfiguration.Default) {}
if (moduleMapping !== ModuleMapping.EMPTY) {
return@DataIndexer mapOf(file.nameWithoutExtension to moduleMapping.moduleData.annotations.map(ClassId::fromString))
}
} catch (e: Exception) {
// Exceptions are already reported in KotlinModuleMappingIndex
emptyMap()
}
emptyMap()
}
}

View File

@@ -73,20 +73,19 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
override fun getVersion(): Int = 5
override fun getIndexer(): DataIndexer<String, PackageParts, FileContent> {
return DataIndexer<String, PackageParts, FileContent> { inputData ->
val content = inputData.content
val file = inputData.file
try {
val moduleMapping = ModuleMapping.loadModuleMapping(content, file.toString(), DeserializationConfiguration.Default)
if (moduleMapping === ModuleMapping.CORRUPTED) {
file.refresh(true, false)
}
return@DataIndexer moduleMapping.packageFqName2Parts
override fun getIndexer(): DataIndexer<String, PackageParts, FileContent> = DataIndexer { inputData ->
val content = inputData.content
val file = inputData.file
try {
val moduleMapping = ModuleMapping.loadModuleMapping(content, file.toString(), DeserializationConfiguration.Default) {
// Do nothing; it's OK for an IDE index to just ignore incompatible module files
}
catch(e: Exception) {
throw RuntimeException("Error on indexing $file", e)
if (moduleMapping === ModuleMapping.CORRUPTED) {
file.refresh(true, false)
}
return@DataIndexer moduleMapping.packageFqName2Parts
} catch (e: Exception) {
throw RuntimeException("Error on indexing $file", e)
}
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.android.configure
import com.android.tools.idea.gradle.project.sync.GradleSyncInvoker
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.JavaSdkVersion
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.idea.configuration.AndroidGradle
import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator
import org.jetbrains.kotlin.idea.configuration.getBuildSystemType
import org.jetbrains.kotlin.idea.util.projectStructure.version
import org.jetbrains.kotlin.idea.versions.MAVEN_STDLIB_ID_JDK7
import org.jetbrains.kotlin.idea.versions.hasJreSpecificRuntime
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
class KotlinAndroidGradleModuleConfigurator internal constructor() : KotlinWithGradleConfigurator() {
override val name: String = NAME
override val targetPlatform: TargetPlatform = JvmPlatform
override val presentableText: String = "Android with Gradle"
public override fun isApplicable(module: Module): Boolean = module.getBuildSystemType() == AndroidGradle
override val kotlinPluginName: String = KOTLIN_ANDROID
override fun getKotlinPluginExpression(forKotlinDsl: Boolean): String =
if (forKotlinDsl) "kotlin(\"android\")" else "id 'org.jetbrains.kotlin.android' "
override fun addElementsToFile(file: PsiFile, isTopLevelProjectFile: Boolean, version: String): Boolean {
val manipulator = getManipulator(file, false)
val sdk = ModuleUtil.findModuleForPsiElement(file)?.let { ModuleRootManager.getInstance(it).sdk }
val jvmTarget = getJvmTarget(sdk, version)
return if (isTopLevelProjectFile) {
manipulator.configureProjectBuildScript(kotlinPluginName, version)
}
else {
manipulator.configureModuleBuildScript(
kotlinPluginName,
getKotlinPluginExpression(file.isKtDsl()),
getStdlibArtifactName(sdk, version),
version,
jvmTarget
)
}
}
override fun getStdlibArtifactName(sdk: Sdk?, version: String): String {
if (sdk != null && hasJreSpecificRuntime(version)) {
val sdkVersion = sdk.version
if (sdkVersion != null && sdkVersion.isAtLeast(JavaSdkVersion.JDK_1_8)) {
// Android dex can't convert our kotlin-stdlib-jre8 artifact, so use jre7 instead (KT-16530)
return MAVEN_STDLIB_ID_JDK7
}
}
return super.getStdlibArtifactName(sdk, version)
}
@JvmSuppressWildcards
override fun configure(project: Project, excludeModules: Collection<Module>) {
super.configure(project, excludeModules)
// Sync after changing build scripts
GradleSyncInvoker.getInstance().requestProjectSync(project, GradleSyncInvoker.Request.projectModified())
}
companion object {
private val NAME = "android-gradle"
private val KOTLIN_ANDROID = "kotlin-android"
}
}

View File

@@ -54,7 +54,7 @@ dependencies {
sourceSets {
"main" {
projectDefault()
resources.srcDir("res").apply { include("**") }
resources.srcDir("res")
}
"test" { projectDefault() }
}

View File

@@ -53,7 +53,7 @@ dependencies {
sourceSets {
"main" {
projectDefault()
resources.srcDir("res").apply { include("**") }
resources.srcDir("res")
}
"test" { projectDefault() }
}

View File

@@ -54,7 +54,7 @@ dependencies {
sourceSets {
"main" {
projectDefault()
resources.srcDir("res").apply { include("**") }
resources.srcDir("res")
}
"test" { projectDefault() }
}

View File

@@ -54,7 +54,7 @@ dependencies {
sourceSets {
"main" {
projectDefault()
resources.srcDir("res").apply { include("**") }
resources.srcDir("res")
}
"test" { projectDefault() }
}

View File

@@ -54,7 +54,7 @@ dependencies {
sourceSets {
"main" {
projectDefault()
resources.srcDir("res").apply { include("**") }
resources.srcDir("res")
}
"test" { projectDefault() }
}

View File

@@ -70,6 +70,7 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>

View File

@@ -0,0 +1,84 @@
<idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPCommonFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPJSFrameworkSupportProvider"/>
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
<projectResolve implementation="org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension" order="last"/>
<projectResolve implementation="org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension" order="last"/>
<projectResolve implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" order="last"/>
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.core.script.ReloadGradleTemplatesOnSync"/>
<localInspection
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection"
displayName="Kotlin Gradle and IDE plugins versions are different"
groupName="Kotlin"
enabledByDefault="true"
language="Groovy"
hasStaticDescription="true"
level="WARNING"/>
<localInspection
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DifferentStdlibGradleVersionInspection"
displayName="Kotlin library and Gradle plugin versions are different"
groupName="Kotlin"
enabledByDefault="true"
language="Groovy"
hasStaticDescription="true"
level="WARNING"/>
<localInspection
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DeprecatedGradleDependencyInspection"
displayName="Deprecated library is used in Gradle"
groupName="Kotlin"
enabledByDefault="true"
language="Groovy"
hasStaticDescription="true"
level="WARNING"/>
<localInspection
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.GradleKotlinxCoroutinesDeprecationInspection"
displayName="kotlinx.coroutines dependencies should be updated in Gradle for using with Kotlin 1.3+"
groupPath="Kotlin,Migration"
groupName="Gradle"
enabledByDefault="true"
language="Groovy"
hasStaticDescription="true"
level="ERROR"/>
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestClassGradleConfigurationProducer"/>
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestMethodGradleConfigurationProducer"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.core.script.GradleScriptDefinitionsContributor" order="first"/>
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMultiplatformModuleBuilder"/>
</extensions>
</idea-plugin>

View File

@@ -78,6 +78,7 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>

View File

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40">
<defs>
<linearGradient id="kotlin-a" x1="2.195%" x2="91.789%" y1="91.369%" y2="0%">
<stop offset="0%" stop-color="#8F67FF" stop-opacity=".987"/>
<stop offset="56.707%" stop-color="#F9A02F" stop-opacity=".993"/>
<stop offset="100%" stop-color="#F7861E"/>
</linearGradient>
</defs>
<g fill="none" fill-rule="evenodd">
<polygon fill="#0EAEFF" points="4 4 4 35.995 36.001 35.995 20.045 19.925 36.001 4"/>
<polygon fill="url(#kotlin-a)" points="20.064 4 4 20.893 4 35.995 20.041 19.925 35.995 4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 631 B

View File

@@ -17,9 +17,9 @@
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.codeInsight.navigation.NavigationUtil
import com.intellij.ide.util.EditorHelper
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
@@ -177,20 +177,14 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
}
override fun invokeImpl(project: Project, editor: Editor?, file: PsiFile) {
if (editor == null) return
val element = element ?: return
val callableInfo = callableInfos.first()
val fileForBuilder: KtFile
val editorForBuilder: Editor
if (file is KtFile) {
fileForBuilder = file
editorForBuilder = editor
} else {
fileForBuilder = element.containingKtFile
EditorHelper.openInEditor(element)
editorForBuilder = FileEditorManager.getInstance(project).selectedTextEditor!!
val fileForBuilder = element.containingKtFile
val editorForBuilder = EditorHelper.openInEditor(element)
if (editorForBuilder != editor) {
NavigationUtil.activateFileWithPsiElement(element)
}
val callableBuilder =
@@ -220,7 +214,7 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
val containers = receiverTypeCandidates
.mapNotNull { candidate -> getDeclarationIfApplicable(project, candidate)?.let { candidate to it } }
chooseContainerElementIfNecessary(containers, editor, popupTitle, false, { it.second }) {
chooseContainerElementIfNecessary(containers, editorForBuilder, popupTitle, false, { it.second }) {
runBuilder(CallablePlacement.WithReceiver(it.first))
}
} else {
@@ -228,7 +222,7 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
"No receiver type candidates: ${element.text} in ${file.text}"
}
chooseContainerElementIfNecessary(callableInfo.possibleContainers, editor, popupTitle, true, { it }) {
chooseContainerElementIfNecessary(callableInfo.possibleContainers, editorForBuilder, popupTitle, true, { it }) {
val container = if (it is KtClassBody) it.parent as KtClassOrObject else it
runBuilder(CallablePlacement.NoReceiver(container))
}

View File

@@ -19,17 +19,20 @@ package org.jetbrains.kotlin.idea.quickfix.crossLanguage
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.QuickFixFactory
import com.intellij.lang.java.beans.PropertyKind
import com.intellij.lang.jvm.JvmClass
import com.intellij.lang.jvm.JvmElement
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.JvmModifiersOwner
import com.intellij.lang.jvm.actions.*
import com.intellij.lang.jvm.types.JvmType
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtilRt
import com.intellij.psi.*
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
import com.intellij.psi.util.PropertyUtilBase
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightElement
@@ -144,9 +147,9 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
}
class CreatePropertyFix(
private val targetClass: JvmClass,
contextElement: KtElement,
propertyInfo: PropertyInfo
contextElement: KtElement,
propertyInfo: PropertyInfo,
private val classOrFileName: String?
) : CreateCallableFromUsageFix<KtElement>(contextElement, listOf(propertyInfo)) {
override fun getFamilyName() = "Add property"
override fun getText(): String {
@@ -157,7 +160,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
append("lateinit ")
}
append(if (info.writable) "var" else "val")
append("' property '${info.name}' to '${targetClass.name}'")
append("' property '${info.name}' to '$classOrFileName'")
}
}
}
@@ -324,29 +327,42 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
override fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List<IntentionAction> {
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
return createAddPropertyActions(
targetContainer, listOf(request.visibilityModifier),
request.propertyType, request.propertyName, request.setterRequired, targetClass.name
)
}
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifier(request.visibilityModifier) }
private fun createAddPropertyActions(
targetContainer: KtElement,
modifiers: Iterable<JvmModifier>,
propertyType: JvmType,
propertyName: String,
setterRequired: Boolean,
classOrFileName: String?
): List<IntentionAction> {
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifiers(modifiers) }
if (!modifierBuilder.isValid) return emptyList()
val resolutionFacade = targetContainer.getResolutionFacade()
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
val ktType = (request.propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
val ktType = (propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
val propertyInfo = PropertyInfo(
request.propertyName,
TypeInfo.Empty,
TypeInfo(ktType, Variance.INVARIANT),
request.setterRequired,
listOf(targetContainer),
modifierList = modifierBuilder.modifierList,
withInitializer = true
propertyName,
TypeInfo.Empty,
TypeInfo(ktType, Variance.INVARIANT),
setterRequired,
listOf(targetContainer),
modifierList = modifierBuilder.modifierList,
withInitializer = true
)
val propertyInfos = if (request.setterRequired) {
val propertyInfos = if (setterRequired) {
listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true))
}
else {
} else {
listOf(propertyInfo)
}
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
return propertyInfos.map { CreatePropertyFix(targetContainer, it, classOrFileName) }
}
override fun createAddFieldActions(targetClass: JvmClass, request: CreateFieldRequest): List<IntentionAction> {
@@ -382,7 +398,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
else {
listOf(propertyInfo(false))
}
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
return propertyInfos.map { CreatePropertyFix(targetContainer, it, targetClass.name) }
}
override fun createAddMethodActions(targetClass: JvmClass, request: CreateMethodRequest): List<IntentionAction> {
@@ -410,11 +426,27 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
preferEmptyBody = true
)
val targetClassName = targetClass.name
val action = object : CreateCallableFromUsageFix<KtElement>(targetContainer, listOf(functionInfo)) {
override fun getFamilyName() = "Add method"
override fun getText() = "Add method '$methodName' to '$targetClassName'"
}
return listOf(action)
val nameAndKind = PropertyUtilBase.getPropertyNameAndKind(methodName) ?: return listOf(action)
val propertyType = (request.expectedParameters.singleOrNull()?.expectedTypes ?: request.returnType)
.firstOrNull { JvmPsiConversionHelper.getInstance(targetContainer.project).convertType(it.theType) != PsiType.VOID }
?: return listOf(action)
return createAddPropertyActions(
targetContainer,
request.modifiers,
propertyType.theType,
nameAndKind.first,
nameAndKind.second == PropertyKind.SETTER,
targetClass.name
)
}
override fun createAddAnnotationActions(target: JvmModifiersOwner, request: AnnotationRequest): List<IntentionAction> {

View File

@@ -17,17 +17,19 @@
package org.jetbrains.kotlin.idea.quickfix.crossLanguage
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.codeInsight.daemon.impl.quickfix.CreateParameterFromUsageFix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.QuickFixFactory
import com.intellij.lang.java.beans.PropertyKind
import com.intellij.lang.jvm.*
import com.intellij.lang.jvm.actions.*
import com.intellij.lang.jvm.types.JvmType
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtilRt
import com.intellij.psi.*
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
import com.intellij.psi.util.PropertyUtilBase
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightElement
@@ -142,9 +144,9 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
}
class CreatePropertyFix(
private val targetClass: JvmClass,
contextElement: KtElement,
propertyInfo: PropertyInfo
propertyInfo: PropertyInfo,
private val classOrFileName: String?
) : CreateCallableFromUsageFix<KtElement>(contextElement, listOf(propertyInfo)) {
override fun getFamilyName() = "Add property"
override fun getText(): String {
@@ -155,7 +157,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
append("lateinit ")
}
append(if (info.writable) "var" else "val")
append("' property '${info.name}' to '${targetClass.name}'")
append("' property '${info.name}' to '$classOrFileName'")
}
}
}
@@ -322,29 +324,43 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
override fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List<IntentionAction> {
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
return createAddPropertyActions(
targetContainer, listOf(request.visibilityModifier),
request.propertyType, request.propertyName, request.setterRequired, targetClass.name
)
}
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifier(request.visibilityModifier) }
private fun createAddPropertyActions(
targetContainer: KtElement,
modifiers: Iterable<JvmModifier>,
propertyType: JvmType,
propertyName: String,
setterRequired: Boolean,
classOrFileName: String?
): List<IntentionAction> {
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifiers(modifiers) }
if (!modifierBuilder.isValid) return emptyList()
val resolutionFacade = targetContainer.getResolutionFacade()
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
val ktType = (request.propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
val ktType = (propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
val propertyInfo = PropertyInfo(
request.propertyName,
propertyName,
TypeInfo.Empty,
TypeInfo(ktType, Variance.INVARIANT),
request.setterRequired,
setterRequired,
listOf(targetContainer),
modifierList = modifierBuilder.modifierList,
withInitializer = true
)
val propertyInfos = if (request.setterRequired) {
val propertyInfos = if (setterRequired) {
listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true))
}
else {
listOf(propertyInfo)
}
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
return propertyInfos.map { CreatePropertyFix(targetContainer, it, classOrFileName) }
}
override fun createAddFieldActions(targetClass: JvmClass, request: CreateFieldRequest): List<IntentionAction> {
@@ -380,7 +396,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
else {
listOf(propertyInfo(false))
}
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
return propertyInfos.map { CreatePropertyFix(targetContainer, it, targetClass.name) }
}
override fun createAddMethodActions(targetClass: JvmClass, request: CreateMethodRequest): List<IntentionAction> {
@@ -412,7 +428,22 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
override fun getFamilyName() = "Add method"
override fun getText() = "Add method '$methodName' to '$targetClassName'"
}
return listOf(action)
val nameAndKind = PropertyUtilBase.getPropertyNameAndKind(methodName) ?: return listOf(action)
val propertyType = (request.expectedParameters.singleOrNull()?.expectedTypes ?: request.returnType)
.firstOrNull { JvmPsiConversionHelper.getInstance(targetContainer.project).convertType(it.theType) != PsiType.VOID }
?: return listOf(action)
return createAddPropertyActions(
targetContainer,
request.modifiers,
propertyType.theType,
nameAndKind.first,
nameAndKind.second == PropertyKind.SETTER,
targetClass.name
)
}
override fun createAddAnnotationActions(target: JvmModifiersOwner, request: AnnotationRequest): List<IntentionAction> {

View File

@@ -0,0 +1,152 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.update
import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.ide.plugins.PluginNode
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.idea.util.isDev
import org.jetbrains.kotlin.idea.util.isEap
import java.io.IOException
import java.net.URL
import java.util.*
import javax.xml.bind.JAXBContext
import javax.xml.bind.JAXBException
import javax.xml.bind.annotation.*
class GooglePluginUpdateVerifier : PluginUpdateVerifier() {
override val verifierName: String
get() = "Android Studio"
// Verifies if a plugin can be installed in Android Studio 3.2+.
// Currently used only by KotlinPluginUpdater.
override fun verify(pluginDescriptor: IdeaPluginDescriptor): PluginVerifyResult? {
if (pluginDescriptor.pluginId.idString != KOTLIN_PLUGIN_ID) {
return null
}
val version = pluginDescriptor.version
if (isEap(version) || isDev(version)) {
return PluginVerifyResult.accept()
}
try {
val url = URL(METADATA_FILE_URL)
val stream = url.openStream()
val context = JAXBContext.newInstance(PluginCompatibility::class.java)
val unmarshaller = context.createUnmarshaller()
val pluginCompatibility = unmarshaller.unmarshal(stream) as PluginCompatibility
val release = getRelease(pluginCompatibility)
?: return PluginVerifyResult.decline("No verified versions for this build.")
return if (release.plugins().any { KOTLIN_PLUGIN_ID == it.id && version == it.version })
PluginVerifyResult.accept()
else
PluginVerifyResult.decline("Version to be verified.")
} catch (e: Exception) {
LOG.info("Exception when verifying plugin ${pluginDescriptor.pluginId.idString} version $version", e)
return when (e) {
is IOException ->
PluginVerifyResult.decline("unable to connect to compatibility verification repository")
is JAXBException -> PluginVerifyResult.decline("unable to parse compatibility verification metadata")
else -> PluginVerifyResult.decline("exception during verification ${e.message}")
}
}
}
private fun getRelease(pluginCompatibility: PluginCompatibility): StudioRelease? {
for (studioRelease in pluginCompatibility.releases()) {
if (buildInRange(studioRelease.name, studioRelease.sinceBuild, studioRelease.untilBuild)) {
return studioRelease
}
}
return null
}
private fun buildInRange(name: String?, sinceBuild: String?, untilBuild: String?): Boolean {
val descriptor = PluginNode()
descriptor.name = name
descriptor.sinceBuild = sinceBuild
descriptor.untilBuild = untilBuild
return PluginManagerCore.isCompatible(descriptor)
}
companion object {
private const val KOTLIN_PLUGIN_ID = "org.jetbrains.kotlin"
private const val METADATA_FILE_URL = "https://dl.google.com/android/studio/plugins/compatibility.xml"
private val LOG = Logger.getInstance(GooglePluginUpdateVerifier::class.java)
private fun PluginCompatibility.releases() = studioRelease ?: emptyArray()
private fun StudioRelease.plugins() = ideaPlugin ?: emptyArray()
@XmlRootElement(name = "plugin-compatibility")
@XmlAccessorType(XmlAccessType.FIELD)
class PluginCompatibility {
@XmlElement(name = "studio-release")
var studioRelease: Array<StudioRelease>? = null
override fun toString(): String {
return "PluginCompatibility(studioRelease=${Arrays.toString(studioRelease)})"
}
}
@XmlAccessorType(XmlAccessType.FIELD)
class StudioRelease {
@XmlAttribute(name = "until-build")
var untilBuild: String? = null
@XmlAttribute(name = "since-build")
var sinceBuild: String? = null
@XmlAttribute
var name: String? = null
@XmlAttribute
var channel: String? = null
@XmlElement(name = "idea-plugin")
var ideaPlugin: Array<IdeaPlugin>? = null
override fun toString(): String {
return "StudioRelease(" +
"untilBuild=$untilBuild, name=$name, ideaPlugin=${Arrays.toString(ideaPlugin)}, " +
"sinceBuild=$sinceBuild, channel=$channel" +
")"
}
}
@XmlAccessorType(XmlAccessType.FIELD)
class IdeaPlugin {
@XmlAttribute
var id: String? = null
@XmlAttribute
var sha256: String? = null
@XmlAttribute
var channel: String? = null
@XmlAttribute
var version: String? = null
@XmlElement(name = "idea-version")
var ideaVersion: IdeaVersion? = null
override fun toString(): String {
return "IdeaPlugin(id=$id, sha256=$sha256, ideaVersion=$ideaVersion, channel=$channel, version=$version)"
}
}
@XmlAccessorType(XmlAccessType.FIELD)
class IdeaVersion {
@XmlAttribute(name = "until-build")
var untilBuild: String? = null
@XmlAttribute(name = "since-build")
var sinceBuild: String? = null
override fun toString(): String {
return "IdeaVersion(untilBuild=$untilBuild, sinceBuild=$sinceBuild)"
}
}
}
}

View File

@@ -24,7 +24,10 @@ import com.intellij.lang.jvm.actions.*
import com.intellij.lang.jvm.types.JvmSubstitutor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Pair.pair
import com.intellij.psi.*
import com.intellij.psi.PsiJvmSubstitutor
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiSubstitutor
import com.intellij.psi.PsiType
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
@@ -32,8 +35,6 @@ import org.jetbrains.kotlin.asJava.toLightElements
import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.uast.UParameter
import org.jetbrains.uast.UastContext
import org.jetbrains.uast.toUElement
import org.junit.Assert
@@ -399,16 +400,16 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
""".trim().trimMargin())
myFixture.launchAction(
createPropertyActions(
myFixture.atCaret(),
MemberRequest.Property(
propertyName = "baz",
visibilityModifier = JvmModifier.PUBLIC,
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
getterRequired = true,
setterRequired = true
)
).findWithText("Add 'var' property 'baz' to 'Foo'")
createMethodActions(
myFixture.atCaret(),
SimpleMethodRequest(
project,
methodName = "setBaz",
modifiers = listOf(JvmModifier.PUBLIC),
returnType = expectedTypes(),
parameters = expectedParams(PsiType.getTypeByName("java.lang.String", project, project.allScope()))
)
).findWithText("Add 'var' property 'baz' to 'Foo'")
)
myFixture.checkResult("""
|class Foo {
@@ -427,16 +428,16 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
""".trim().trimMargin())
myFixture.launchAction(
createPropertyActions(
myFixture.atCaret(),
MemberRequest.Property(
propertyName = "baz",
visibilityModifier = JvmModifier.PUBLIC,
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
getterRequired = true,
setterRequired = true
)
).findWithText("Add 'lateinit var' property 'baz' to 'Foo'")
createMethodActions(
myFixture.atCaret(),
SimpleMethodRequest(
project,
methodName = "setBaz",
modifiers = listOf(JvmModifier.PUBLIC),
returnType = expectedTypes(),
parameters = expectedParams(PsiType.getTypeByName("java.lang.String", project, project.allScope()))
)
).findWithText("Add 'lateinit var' property 'baz' to 'Foo'")
)
myFixture.checkResult("""
|class Foo {
@@ -502,10 +503,6 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
}
private fun createPropertyActions(atCaret: JvmClass, property: MemberRequest.Property): List<IntentionAction> =
com.intellij.lang.jvm.actions.EP_NAME.extensions.flatMap { it.createAddPropertyActions(atCaret, property) }
private fun createFieldActions(atCaret: JvmClass, fieldRequest: CreateFieldRequest): List<IntentionAction> =
com.intellij.lang.jvm.actions.EP_NAME.extensions.flatMap { it.createAddFieldActions(atCaret, fieldRequest) }
@@ -517,16 +514,16 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
""".trim().trimMargin())
myFixture.launchAction(
createPropertyActions(
myFixture.atCaret(),
MemberRequest.Property(
propertyName = "baz",
visibilityModifier = JvmModifier.PUBLIC,
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
getterRequired = true,
setterRequired = false
)
).findWithText("Add 'val' property 'baz' to 'Foo'")
createMethodActions(
myFixture.atCaret(),
SimpleMethodRequest(
project,
methodName = "getBaz",
modifiers = listOf(JvmModifier.PUBLIC),
returnType = expectedTypes(PsiType.getTypeByName("java.lang.String", project, project.allScope())),
parameters = expectedParams()
)
).findWithText("Add 'val' property 'baz' to 'Foo'")
)
myFixture.checkResult("""
|class Foo {
@@ -537,13 +534,6 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
""".trim().trimMargin(), true)
}
private fun makeParams(vararg psyTypes: PsiType): List<UParameter> {
val uastContext = UastContext(myFixture.project)
val factory = JavaPsiFacade.getElementFactory(myFixture.project)
val parameters = psyTypes.mapIndexed { index, psiType -> factory.createParameter("param$index", psiType) }
return parameters.map { uastContext.convertElement(it, null, UParameter::class.java) as UParameter }
}
private fun expectedTypes(vararg psiTypes: PsiType) = psiTypes.map { expectedType(it) }
private fun expectedParams(vararg psyTypes: PsiType) =

View File

@@ -402,14 +402,14 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
""".trim().trimMargin())
myFixture.launchAction(
createPropertyActions(
createMethodActions(
myFixture.atCaret(),
MemberRequest.Property(
propertyName = "baz",
visibilityModifier = JvmModifier.PUBLIC,
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
getterRequired = true,
setterRequired = true
SimpleMethodRequest(
project,
methodName = "setBaz",
modifiers = listOf(JvmModifier.PUBLIC),
returnType = expectedTypes(),
parameters = expectedParams(PsiType.getTypeByName("java.lang.String", project, project.allScope()))
)
).findWithText("Add 'var' property 'baz' to 'Foo'")
)
@@ -430,14 +430,14 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
""".trim().trimMargin())
myFixture.launchAction(
createPropertyActions(
createMethodActions(
myFixture.atCaret(),
MemberRequest.Property(
propertyName = "baz",
visibilityModifier = JvmModifier.PUBLIC,
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
getterRequired = true,
setterRequired = true
SimpleMethodRequest(
project,
methodName = "setBaz",
modifiers = listOf(JvmModifier.PUBLIC),
returnType = expectedTypes(),
parameters = expectedParams(PsiType.getTypeByName("java.lang.String", project, project.allScope()))
)
).findWithText("Add 'lateinit var' property 'baz' to 'Foo'")
)
@@ -505,10 +505,6 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
}
private fun createPropertyActions(atCaret: JvmClass, property: MemberRequest.Property): List<IntentionAction> =
com.intellij.lang.jvm.actions.EP_NAME.extensions.flatMap { it.createAddPropertyActions(atCaret, property) }
private fun createFieldActions(atCaret: JvmClass, fieldRequest: CreateFieldRequest): List<IntentionAction> =
com.intellij.lang.jvm.actions.EP_NAME.extensions.flatMap { it.createAddFieldActions(atCaret, fieldRequest) }
@@ -520,14 +516,14 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
""".trim().trimMargin())
myFixture.launchAction(
createPropertyActions(
createMethodActions(
myFixture.atCaret(),
MemberRequest.Property(
propertyName = "baz",
visibilityModifier = JvmModifier.PUBLIC,
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
getterRequired = true,
setterRequired = false
SimpleMethodRequest(
project,
methodName = "getBaz",
modifiers = listOf(JvmModifier.PUBLIC),
returnType = expectedTypes(PsiType.getTypeByName("java.lang.String", project, project.allScope())),
parameters = expectedParams()
)
).findWithText("Add 'val' property 'baz' to 'Foo'")
)

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.jps.build
import com.intellij.testFramework.UsefulTestCase
import com.intellij.util.containers.HashMap
import com.intellij.util.containers.StringInterner
import org.jetbrains.kotlin.TestWithWorkingDir
import org.jetbrains.kotlin.build.JvmSourceRoot
@@ -78,13 +77,14 @@ abstract class AbstractJvmLookupTrackerTest : AbstractLookupTrackerTest() {
override fun runCompiler(filesToCompile: Iterable<File>, env: JpsCompilerEnvironment): Any? {
val moduleFile = makeModuleFile(
name = "test",
isTest = true,
outputDir = outDir,
sourcesToCompile = filesToCompile.toList(),
javaSourceRoots = listOf(JvmSourceRoot(srcDir, null)),
classpath = listOf(outDir, ForTestCompileRuntime.runtimeJarForTests()).filter { it.exists() },
friendDirs = emptyList()
name = "test",
isTest = true,
outputDir = outDir,
sourcesToCompile = filesToCompile.toList(),
commonSources = emptyList(),
javaSourceRoots = listOf(JvmSourceRoot(srcDir, null)),
classpath = listOf(outDir, ForTestCompileRuntime.runtimeJarForTests()).filter { it.exists() },
friendDirs = emptyList()
)
val args = K2JVMCompilerArguments().apply {

View File

@@ -909,6 +909,11 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
runTest("jps-plugin/testData/incremental/pureKotlin/ourClassReferenced/");
}
@TestMetadata("overloadInlined")
public void testOverloadInlined() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/overloadInlined/");
}
@TestMetadata("packageConstantChanged")
public void testPackageConstantChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/packageConstantChanged/");
@@ -1099,6 +1104,11 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
runTest("jps-plugin/testData/incremental/pureKotlin/returnTypeChanged/");
}
@TestMetadata("secondaryConstructorInlined")
public void testSecondaryConstructorInlined() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/secondaryConstructorInlined/");
}
@TestMetadata("simpleClassDependency")
public void testSimpleClassDependency() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/simpleClassDependency/");

View File

@@ -41,16 +41,17 @@ class ClasspathOrderTest : TestCaseWithTmpdir() {
fun testClasspathOrderForModuleScriptBuild() {
val xmlContent = KotlinModuleXmlBuilder().addModule(
"name",
File(tmpdir, "output").absolutePath,
listOf(sourceDir),
listOf(JvmSourceRoot(sourceDir)),
listOf(PathUtil.kotlinPathsForDistDirectory.stdlibPath),
null,
JavaModuleBuildTargetType.PRODUCTION.typeId,
JavaModuleBuildTargetType.PRODUCTION.isTests,
setOf(),
emptyList()
"name",
File(tmpdir, "output").absolutePath,
listOf(sourceDir),
listOf(JvmSourceRoot(sourceDir)),
listOf(PathUtil.kotlinPathsForDistDirectory.stdlibPath),
emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.typeId,
JavaModuleBuildTargetType.PRODUCTION.isTests,
setOf(),
emptyList()
).asText().toString()
val xml = File(tmpdir, "module.xml")

View File

@@ -33,6 +33,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Arrays.asList(new File("s1"), new File("s2")),
Collections.singletonList(new JvmSourceRoot(new File("java"), null)),
Arrays.asList(new File("cp1"), new File("cp2")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
@@ -49,6 +50,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Arrays.asList(new File("s1"), new File("s2")),
Collections.emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
@@ -66,6 +68,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Arrays.asList(new File("s1"), new File("s2")),
Collections.emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
@@ -78,6 +81,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Arrays.asList(new File("s12"), new File("s22")),
Collections.emptyList(),
Arrays.asList(new File("cp12"), new File("cp22")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.TEST.getTypeId(),
JavaModuleBuildTargetType.TEST.isTests(),
@@ -95,6 +99,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList(),
new File("/path/to/modular/jdk"),
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),

View File

@@ -28,12 +28,9 @@ import org.jetbrains.kotlin.compilerRunner.JpsCompilerEnvironment
import org.jetbrains.kotlin.compilerRunner.JpsKotlinCompilerRunner
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.ChangesCollector
import org.jetbrains.kotlin.incremental.IncrementalCompilationComponentsImpl
import org.jetbrains.kotlin.incremental.IncrementalJvmCache
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.updateIncrementalCache
import org.jetbrains.kotlin.jps.build.KotlinBuilder
import org.jetbrains.kotlin.jps.build.KotlinDirtySourceFilesHolder
import org.jetbrains.kotlin.jps.incremental.JpsIncrementalCache
@@ -131,7 +128,7 @@ class KotlinJvmModuleBuildTarget(compileContext: CompileContext, jpsModuleBuildT
moduleFile
)
} finally {
if (System.getProperty("kotlin.jps.delete.module.file.after.build") != "false") {
if (System.getProperty(DELETE_MODULE_FILE_PROPERTY) != "false") {
moduleFile.delete()
}
}
@@ -153,6 +150,7 @@ class KotlinJvmModuleBuildTarget(compileContext: CompileContext, jpsModuleBuildT
val friendDirs = target.friendOutputDirs
val moduleSources = collectSourcesToCompile(target, dirtyFilesHolder)
val commonSources = emptyList<File>() // TODO: pass common sources here
val hasDirtyOrRemovedSources = checkShouldCompileAndLog(target, dirtyFilesHolder, moduleSources)
if (hasDirtyOrRemovedSources) hasDirtySources = true
@@ -163,6 +161,7 @@ class KotlinJvmModuleBuildTarget(compileContext: CompileContext, jpsModuleBuildT
moduleSources,
target.findSourceRoots(context),
target.findClassPathRoots(),
commonSources,
target.findModularJdkRoot(),
kotlinModuleId.type,
isTests,

View File

@@ -0,0 +1,11 @@
================ Step #1 =================
Cleaning output files:
out/production/module/DummyKt.class
out/production/module/META-INF/module.kotlin_module
End of files
Compiling files:
src/dummy.kt
End of files
Exit code: OK
------------------------------------------

View File

@@ -0,0 +1 @@
fun dummy() {}

View File

@@ -0,0 +1,2 @@
fun overloaded(x: Int) {}
fun overloaded(s: String) {}

View File

@@ -0,0 +1,3 @@
inline fun overloadedInline() {
overloaded("overloadedInline")
}

View File

@@ -0,0 +1,3 @@
fun useOverloaded() {
overloaded("useOverloadedInline")
}

View File

@@ -0,0 +1,3 @@
fun useOverloadedInline() {
overloadedInline()
}

View File

@@ -0,0 +1,4 @@
class Err constructor(msg: String?, unused: Any?) {
constructor() : this(null, null)
constructor(msg: String) : this(msg, null)
}

View File

@@ -0,0 +1,11 @@
================ Step #1 =================
Cleaning output files:
out/production/module/DummyKt.class
out/production/module/META-INF/module.kotlin_module
End of files
Compiling files:
src/dummy.kt
End of files
Exit code: OK
------------------------------------------

View File

@@ -0,0 +1,3 @@
inline fun createErr() {
Err("createErr")
}

View File

@@ -0,0 +1 @@
fun dummy() {}

View File

@@ -0,0 +1,3 @@
fun useCreateErr() {
createErr()
}

View File

@@ -47,6 +47,8 @@ var JsInvocation.descriptor: CallableDescriptor? by MetadataProperty(default = n
var JsInvocation.psiElement: PsiElement? by MetadataProperty(default = null)
var JsNameRef.isJsCall: Boolean by MetadataProperty(default = false)
var JsNameRef.inlineStrategy: InlineStrategy? by MetadataProperty(default = null)
var JsNameRef.descriptor: CallableDescriptor? by MetadataProperty(default = null)

View File

@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.js.inline.context.FunctionContext;
import org.jetbrains.kotlin.js.inline.context.InliningContext;
import org.jetbrains.kotlin.js.inline.context.NamingContext;
import org.jetbrains.kotlin.js.inline.util.*;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata;
import org.jetbrains.kotlin.resolve.inline.InlineStrategy;
@@ -62,7 +61,13 @@ public class JsInliner extends JsVisitorWithContextImpl {
node -> node instanceof JsInvocation && hasToBeInlined((JsInvocation) node);
private int inlineFunctionDepth;
private final Map<JsWrapperKey, Map<JsName, JsExpression>> replacementsInducedByWrappers = new HashMap<>();
private final Map<JsWrapperKey, Map<JsName, JsNameRef>> replacementsInducedByWrappers = new HashMap<>();
private final Map<JsName, String> inverseNameBindings;
private Map<JsName, String> existingNameBindings = new HashMap<>();
private final List<JsNameBinding> additionalNameBindings = new ArrayList<>();
public static void process(
@NotNull JsConfig.Reporter reporter,
@@ -75,6 +80,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
) {
Map<JsName, FunctionWithWrapper> functions = CollectUtilsKt.collectNamedFunctionsAndWrappers(fragments);
Map<String, FunctionWithWrapper> accessors = CollectUtilsKt.collectAccessors(fragments);
Map<JsName, String> inverseNameBindings = CollectUtilsKt.collectNameBindings(fragments);
DummyAccessorInvocationTransformer accessorInvocationTransformer = new DummyAccessorInvocationTransformer();
for (JsProgramFragment fragment : fragmentsToProcess) {
@@ -82,7 +88,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
accessorInvocationTransformer.accept(fragment.getInitializerBlock());
}
FunctionReader functionReader = new FunctionReader(reporter, config, currentModuleName, fragments);
JsInliner inliner = new JsInliner(config, functions, accessors, functionReader, trace);
JsInliner inliner = new JsInliner(config, functions, accessors, inverseNameBindings, functionReader, trace);
for (JsStatement statement : importStatements) {
inliner.processImportStatement(statement);
@@ -90,8 +96,9 @@ public class JsInliner extends JsVisitorWithContextImpl {
for (JsProgramFragment fragment : fragmentsToProcess) {
inliner.existingImports.clear();
inliner.additionalNameBindings.clear();
inliner.existingNameBindings = CollectUtilsKt.collectNameBindings(Collections.singletonList(fragment));
inliner.inliningContexts.push(inliner.new JsInliningContext(inliner.new ListContext<JsStatement>()));
inliner.acceptStatement(fragment.getDeclarationBlock());
// There can be inlined function in top-level initializers, we need to optimize them as well
@@ -101,8 +108,8 @@ public class JsInliner extends JsVisitorWithContextImpl {
inliner.accept(initWrapper);
initWrapper.getStatements().remove(initWrapper.getStatements().size() - 1);
inliner.inliningContexts.pop();
fragment.getInitializerBlock().getStatements().addAll(0, initWrapper.getStatements());
fragment.getNameBindings().addAll(inliner.additionalNameBindings);
}
for (JsProgramFragment fragment : fragmentsToProcess) {
@@ -117,6 +124,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
@NotNull JsConfig config,
@NotNull Map<JsName, FunctionWithWrapper> functions,
@NotNull Map<String, FunctionWithWrapper> accessors,
@NotNull Map<JsName, String> inverseNameBindings,
@NotNull FunctionReader functionReader,
@NotNull DiagnosticSink trace
) {
@@ -127,6 +135,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
namedFunctionsSet.add(functionWithWrapper.getFunction());
}
this.accessors = accessors;
this.inverseNameBindings = inverseNameBindings;
this.functionReader = functionReader;
this.trace = trace;
@@ -157,8 +166,16 @@ public class JsInliner extends JsVisitorWithContextImpl {
return false;
}
else {
startFunction(function);
return super.visit(function, context);
if (statementContextForInline == null) {
statementContextForInline = getLastStatementLevelContext();
startFunction(function);
boolean result = super.visit(function, context);
statementContextForInline = null;
return result;
} else {
startFunction(function);
return super.visit(function, context);
}
}
}
@@ -171,10 +188,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
}
private void startFunction(@NotNull JsFunction function) {
JsContext<JsStatement> statementContext = statementContextForInline != null ? statementContextForInline :
getLastStatementLevelContext();
inliningContexts.push(new JsInliningContext(statementContext));
inliningContexts.push(new JsInliningContext(statementContextForInline));
assert !inProcessFunctions.contains(function): "Inliner has revisited function";
inProcessFunctions.add(function);
@@ -236,9 +250,8 @@ public class JsInliner extends JsVisitorWithContextImpl {
innerContext.traverse(statements);
statementContexts.pop();
}
else {
statementContextForInline = getLastStatementLevelContext();
} else {
if (statementContextForInline == null) statementContextForInline = getLastStatementLevelContext();
}
startFunction(functionWithWrapper.getFunction());
@@ -396,10 +409,10 @@ public class JsInliner extends JsVisitorWithContextImpl {
@NotNull InliningContext inliningContext
) {
// Apparently we should avoid this trick when we implement fair support for crossinline
Function<JsWrapperKey, Map<JsName, JsExpression>> replacementGen = k -> {
Function<JsWrapperKey, Map<JsName, JsNameRef>> replacementGen = k -> {
JsContext ctx = k.context;
Map<JsName, JsExpression> newReplacements = new HashMap<>();
Map<JsName, JsNameRef> newReplacements = new HashMap<>();
List<JsStatement> copiedStatements = new ArrayList<>();
for (JsStatement statement : wrapper.getStatements()) {
@@ -427,7 +440,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
}
if (name != existingName) {
JsExpression replacement = pureFqn(existingName, null);
JsNameRef replacement = pureFqn(existingName, null);
newReplacements.put(name, replacement);
}
@@ -445,7 +458,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
for (JsName name : definedNames) {
JsName alias = JsScope.declareTemporaryName(name.getIdent());
alias.copyMetadataFrom(name);
JsExpression replacement = pureFqn(alias, null);
JsNameRef replacement = pureFqn(alias, null);
newReplacements.put(name, replacement);
}
@@ -464,9 +477,21 @@ public class JsInliner extends JsVisitorWithContextImpl {
};
JsWrapperKey key = new JsWrapperKey(inliningContext.getStatementContextBeforeCurrentFunction(), originalFunction);
Map<JsName, JsExpression> replacements = replacementsInducedByWrappers.computeIfAbsent(key, replacementGen);
Map<JsName, JsNameRef> replacements = replacementsInducedByWrappers.computeIfAbsent(key, replacementGen);
RewriteUtilsKt.replaceNames(function, replacements);
// Copy nameBinding's for inlined localAlias'es
for (JsNameRef nameRef : replacements.values()) {
JsName name = nameRef.getName();
if (name != null && !existingNameBindings.containsKey(name)) {
String tag = inverseNameBindings.get(name);
if (tag != null) {
existingNameBindings.put(name, tag);
additionalNameBindings.add(new JsNameBinding(tag, name));
}
}
}
}
private static void replaceExpressionsWithLocalAliases(@NotNull JsStatement statement) {

View File

@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsBlock
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
import org.jetbrains.kotlin.js.backend.ast.RecursiveJsVisitor
import org.jetbrains.kotlin.js.inline.util.getCallerQualifier
import org.jetbrains.kotlin.js.backend.ast.metadata.isJsCall
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
// Replaces a.foo.call(a, b) with a.foo(b)
@@ -37,7 +37,11 @@ class RedundantCallElimination(private val root: JsBlock) {
private fun tryEliminate(invocation: JsInvocation) {
if (!isCallInvocation(invocation)) return
val qualifier = getCallerQualifier(invocation) as? JsNameRef ?: return
val call = invocation.qualifier as? JsNameRef ?: return
if (!call.isJsCall) return
val qualifier = call.qualifier as? JsNameRef ?: return
val receiver = qualifier.qualifier as? JsNameRef ?: return
val firstArg = invocation.arguments.firstOrNull() as? JsNameRef ?: return

View File

@@ -230,6 +230,16 @@ fun collectAccessors(fragments: List<JsProgramFragment>): Map<String, FunctionWi
return result
}
fun collectNameBindings(fragments: List<JsProgramFragment>): Map<JsName, String> {
val result = mutableMapOf<JsName, String>()
for (fragment in fragments) {
for (binding in fragment.nameBindings) {
result[binding.name] = binding.key
}
}
return result
}
fun extractFunction(expression: JsExpression) = when (expression) {
is JsFunction -> FunctionWithWrapper(expression, null)
else -> InlineMetadata.decompose(expression)?.function ?: InlineMetadata.tryExtractFunction(expression)

Some files were not shown because too many files have changed in this diff Show More