Compare commits

..

25 Commits

Author SHA1 Message Date
Simon Ogorodnik
667dc57a9f WIP: FIR concurrency 2019-07-30 20:08:31 +03:00
Simon Ogorodnik
d31d29bb61 [FIR] concurrency: non-fir changes 2019-07-30 20:08:12 +03:00
Simon Ogorodnik
80e0da1751 WIP: Concurrency 2019-07-25 04:45:29 +03:00
Simon Ogorodnik
ccceacd8cc WIP: Multithreaded compiler 2019-07-17 19:56:54 +03:00
Simon Ogorodnik
379f564a98 Fixup: t 2019-07-17 16:23:11 +03:00
Simon Ogorodnik
2a4dbb3a2a Remove FirTotalKotlinResolveInIdeTest as no more useful 2019-07-17 16:22:57 +03:00
Simon Ogorodnik
b81716a918 Candidate pool WIP 2019-07-16 21:35:50 +03:00
Simon Ogorodnik
f53001a6e1 WIP: Make call resolver resettable 2019-07-16 21:03:55 +03:00
Simon Ogorodnik
7372bb2e5f WIP: Do not recreate body resolve transformer for each file 2019-07-16 20:57:05 +03:00
Mikhail Glukhikh
abadfc50bd FIR resolve: attempt to skip non-valid groups 2019-07-16 13:45:38 +03:00
Mikhail Glukhikh
b99de17e40 ++ Make ... not resolved 2019-07-16 13:29:57 +03:00
Mikhail Glukhikh
f1374612ed FIR resolve: fix vararg parameter types 2019-07-15 18:44:30 +03:00
Mikhail Glukhikh
11df6091fa Make FirNamedReferenceWithCandidate not resolved, fix receiver completion
Counting it as resolved provokes a lot of difficult to discover errors
2019-07-15 18:21:45 +03:00
Mikhail Glukhikh
d11a4f96f2 FIR resolve: add early protection against cyclic property resolve 2019-07-15 17:47:38 +03:00
Mikhail Glukhikh
0b5a5c6d62 Extract part of utility FIR transformers into TransformUtils 2019-07-15 17:34:07 +03:00
Mikhail Glukhikh
45d3e6eb97 Minor (FIR resolve): replace session with fileSession 2019-07-15 17:32:37 +03:00
Mikhail Glukhikh
b16d53c855 Minor (FIR resolve): remove duplicated check 2019-07-15 17:32:37 +03:00
Mikhail Glukhikh
605cd838d5 FIR: set constructor parameter scope correctly for designated transformer 2019-07-15 17:32:36 +03:00
Mikhail Glukhikh
c2caccc175 FIR: preliminary implementation of delegate resolve #KT-32217 Fixed 2019-07-15 17:32:36 +03:00
Mikhail Glukhikh
6e63310b68 Measure unresolved function call & qualified access # in FIR bench 2019-07-15 17:32:36 +03:00
Simon Ogorodnik
67f2259e1a Use no-op substitutor instead of substitutor with empty map 2019-07-15 17:32:36 +03:00
Mikhail Glukhikh
f76356a4fe ++ FIR2IR test data 2019-07-15 17:32:35 +03:00
Simon Ogorodnik
de08dfbc7f FIR resolve: perform inference completion for property access 2019-07-15 17:32:35 +03:00
Mikhail Glukhikh
d5228afa94 ? FIR: questionable invoke refactoring -- breaks FIR2IR test(s) ? 2019-07-15 17:32:14 +03:00
Mikhail Glukhikh
75d315f5c9 Add test (works only partially) for "type from delegate" 2019-07-15 17:07:33 +03:00
30564 changed files with 432416 additions and 984682 deletions

12
.bunch
View File

@@ -1,7 +1,7 @@
193
201
191
192
191_192
as35_191_192
as36_192
as40
183
182_183
as33_182_183
as34_183
as35

2
.gitattributes vendored
View File

@@ -1,6 +1,4 @@
**/testData/** linguist-vendored
*Generated.java linguist-generated=true
* text=auto
* eol=lf
compiler/cli/bin/* eol=lf
compiler/cli/bin/*.bat eol=crlf

9
.gitignore vendored
View File

@@ -1,9 +1,8 @@
.DS_Store
.idea/shelf
/android.tests.dependencies
/confluence/target
/dependencies/repo
/android.tests.dependencies
/dependencies/android.tests.dependencies
/dist
/local
/gh-pages
@@ -18,7 +17,6 @@ workspace.xml
/jps-plugin/testData/kannotator
/js/js.translator/testData/out/
/js/js.translator/testData/out-min/
/js/js.translator/testData/out-pir/
.gradle/
build/
!**/src/**/build
@@ -28,7 +26,6 @@ build/
.idea/libraries/Gradle*.xml
.idea/libraries/Maven*.xml
.idea/artifacts/PILL_*.xml
.idea/artifacts/KotlinPlugin.xml
.idea/modules
.idea/runConfigurations/JPS_*.xml
.idea/runConfigurations/PILL_*.xml
@@ -50,10 +47,8 @@ build/
.idea/artifacts/kotlin_main_kts_jar.xml
.idea/artifacts/kotlin_compiler_client_embeddable_jar.xml
.idea/artifacts/kotlin_reflect_jar.xml
.idea/jarRepositories.xml
kotlin-ultimate/
node_modules/
.rpt2_cache/
libraries/tools/kotlin-test-js-runner/lib/
libraries/tools/kotlin-source-map-loader/lib/
libraries/tools/kotlin-test-nodejs-runner/lib/
local.properties

8
.idea/artifacts/dist_root.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<component name="ArtifactManager">
<artifact build-on-make="true" name="dist_root">
<output-path>$PROJECT_DIR$/dist</output-path>
<root id="root">
<element id="artifact" artifact-name="dist" />
</root>
</artifact>
</component>

View File

@@ -1,9 +1,6 @@
<component name="ProjectDictionaryState">
<dictionary name="4u7">
<words>
<w>bintray</w>
<w>cacheability</w>
<w>cacheable</w>
<w>cidr</w>
<w>foldable</w>
<w>instrumentator</w>

View File

@@ -1,11 +1,6 @@
<component name="ProjectDictionaryState">
<dictionary name="dmitriy.dolovov">
<words>
<w>commonization</w>
<w>commonize</w>
<w>commonized</w>
<w>commonizer</w>
<w>commonizers</w>
<w>konan</w>
</words>
</dictionary>

View File

@@ -1,7 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="sergey.igushkin">
<words>
<w>klib</w>
</words>
</dictionary>
</component>

View File

@@ -1,9 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="skuzmich">
<words>
<w>anyref</w>
<w>ushr</w>
<w>wasm</w>
</words>
</dictionary>
</component>

View File

@@ -6,13 +6,9 @@
<w>destructured</w>
<w>hacky</w>
<w>impls</w>
<w>inlined</w>
<w>kapt</w>
<w>kotlinc</w>
<w>mutators</w>
<w>parceler</w>
<w>repl</w>
<w>testdata</w>
<w>uast</w>
<w>unbox</w>
<w>unboxed</w>

View File

@@ -99,8 +99,21 @@
<option name="problems">
<list>
<Problem reference="com.intellij.util.JdomKt#element" reason="Removed in 191" />
<Problem reference="com.intellij.util.AstLoadingFilter" reason="Absent in 181. Almost all methods were renamed in 183. Use org.jetbrains.kotlin.util.AstLoadingFilter instead." />
<Problem reference="com.intellij.codeInspection.reference.RefFile#getPsiElement" reason="Absent in 182. Use psiFile extension instead." />
<Problem reference="com.intellij.execution.JavaRunConfigurationExtensionManager#getInstance" reason="Can't be used in Kotlin, because method was replaced with property after J2K in 183. Use JavaRunConfigurationExtensionManagerUtil instead." />
<Problem reference="org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler#addSpace" reason="Method was replaced with outher methods in 182. Use addSpaceEx instead." />
<Problem reference="com.intellij.execution.configurations.RunConfigurationBase" reason="Generalized in 183. Use RunConfigurationBaseAny instead in signatures." />
<Problem reference="com.intellij.execution.configurations.LocatableConfigurationBase" reason="Generalized in 183. Use LocatableConfigurationBaseAny instead in signatures." />
<Problem reference="com.intellij.execution.configurations.ModuleBasedConfiguration" reason="Generalized in 183. Use ModuleBasedConfigurationElement instead." />
<Problem reference="com.intellij.psi.codeStyle.CodeStyleSettingsProvider" reason="Additional method is introduced in 183 instead of deprecated one. Use CodeStyleSettingsProviderCompat instead." />
<Problem reference="com.intellij.openapi.ui.popup.PopupChooserBuilder#PopupChooserBuilder(javax.swing.JList)" reason="Generified in 182. Use PopupChooserBuilderWrapper instead." />
<Problem reference="com.intellij.openapi.editor.event.EditorFactoryListener" reason="Default implementations were added in 183. Use EditorFactoryListenerWrapper for inheritance instead." />
<Problem reference="com.intellij.openapi.diagnostic.LoggerKt#debugOrInfoIfTestMode" reason="Absent in 182." />
<Problem reference="com.intellij.psi.search.PsiSearchHelper.SERVICE" reason="Deprecated since 182. Use psiSearchHelperInstance() instead." />
<Problem reference="org.jetbrains.kotlin.idea.reporter.ITNReporterCompat#submit" reason="parentComponent is nullable in AS" />
<Problem reference="com.intellij.diagnostic.ITNReporter#submit" reason="parentComponent is nullable in AS" />
<Problem reference="com.intellij.codeInspection.dataFlow.Nullness" reason="Deprecated since 182. Use org.jetbrains.kotlin.idea.util.compat.Nullability instead." />
</list>
</option>
</inspection_tool>
@@ -254,7 +267,7 @@
<option name="ignoreAnonymousClassMethods" value="false" />
</inspection_tool>
<inspection_tool class="MissingRecentApi" enabled="true" level="ERROR" enabled_by_default="true">
<option name="sinceBuildString" value="183.3284" />
<option name="sinceBuildString" value="182.0" />
<option name="untilBuildString" value="192.SNAPSHOT" />
</inspection_tool>
<inspection_tool class="MisspelledCompareTo" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -423,21 +436,6 @@
<inspection_tool class="UnnecessaryLabelOnContinueStatement" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnnecessaryQualifierForThis" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UnnecessaryUnboxing" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnstableApiUsage" enabled="true" level="WARNING" enabled_by_default="true">
<option name="unstableApiAnnotations">
<set>
<option value="com.google.common.annotations.Beta" />
<option value="io.reactivex.annotations.Beta" />
<option value="io.reactivex.annotations.Experimental" />
<option value="org.apache.http.annotation.Beta" />
<option value="org.jetbrains.annotations.ApiStatus.Experimental" />
<option value="org.jetbrains.annotations.ApiStatus.Internal" />
<option value="org.jetbrains.annotations.ApiStatus.ScheduledForRemoval" />
<option value="rx.annotations.Beta" />
<option value="rx.annotations.Experimental" />
</set>
</option>
</inspection_tool>
<inspection_tool class="UseOfPropertiesAsHashtable" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UtilityClassWithPublicConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="VolatileLongOrDoubleField" enabled="true" level="WARNING" enabled_by_default="true" />

39
.idea/misc.xml generated
View File

@@ -12,19 +12,46 @@
<item index="2" class="java.lang.String" itemvalue="org.gradle.api.tasks.options.Option" />
</list>
</component>
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
<component name="FacetAutodetectingManager">
<autodetection-disabled>
<facet-type id="Python">
<modules>
<module name="Jet" />
</modules>
</facet-type>
</autodetection-disabled>
</component>
<component name="IdProvider" IDEtalkID="71A301FF1940049D6D82F12C40F1E1D5" />
<component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" />
<option name="OPTION_SCOPE" value="protected" />
<option name="OPTION_HIERARCHY" value="true" />
<option name="OPTION_NAVIGATOR" value="true" />
<option name="OPTION_INDEX" value="true" />
<option name="OPTION_SEPARATE_INDEX" value="true" />
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
<option name="OPTION_DEPRECATED_LIST" value="true" />
<option name="OTHER_OPTIONS" value="" />
<option name="HEAP_SIZE" />
<option name="LOCALE" />
<option name="OPEN_IN_BROWSER" value="true" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/libraries/pom.xml" />
</list>
</option>
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
<option name="myDefaultNotNull" value="org.jetbrains.annotations.NotNull" />
<option name="myNullables">
<value>
<list size="11">
<list size="9">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
@@ -34,14 +61,12 @@
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
<item index="9" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="11">
<list size="9">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="javax.validation.constraints.NotNull" />
@@ -51,8 +76,6 @@
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="9" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
</list>
</value>
</option>

View File

@@ -12,7 +12,6 @@
<list>
<option value=":compiler:generateTests" />
<option value=":compiler:tests-java8:generateTests" />
<option value=":compiler:tests-against-klib:generateTests" />
<option value=":js:js.tests:generateTests" />
<option value=":core:descriptors.runtime:generateTests" />
</list>

8
.idea/vcs.xml generated
View File

@@ -1,13 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CommitMessageInspectionProfile">
<profile version="1.0">
<inspection_tool class="BodyLimit" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GrazieCommit" enabled="true" level="TYPO" enabled_by_default="true" />
<inspection_tool class="SubjectBodySeparation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
<component name="IssueNavigationConfiguration">
<option name="links">
<list>

File diff suppressed because it is too large Load Diff

View File

@@ -39,7 +39,7 @@ In order to build Kotlin distribution you need to have:
For local development, if you're not working on bytecode generation or the standard library, it's OK to have only JDK 1.8 and JDK 9 installed, and to point JDK_16 and JDK_17 environment variables to your JDK 1.8 installation.
You also can use [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties) to setup JDK_* variables.
You also can use [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties) to setup JDK_* variables.
> Note: The JDK 6 for MacOS is not available on Oracle's site. You can [download it here](https://support.apple.com/kb/DL1572).
@@ -73,7 +73,7 @@ command line parameters on the first run:
- `clean` - clean build results
- `dist` - assembles the compiler distribution into `dist/kotlinc/` folder
- `ideaPlugin` - assembles the Kotlin IDEA plugin distribution into `dist/artifacts/ideaPlugin/Kotlin/` folder
- `ideaPlugin` - assembles the Kotlin IDEA plugin distribution into `dist/artifacts/Kotlin` folder
- `install` - build and install all public artifacts into local maven repository
- `runIde` - build IDEA plugin and run IDEA with it
- `coreLibsTest` - build and run stdlib, reflect and kotlin-test tests
@@ -98,13 +98,13 @@ Development for some particular platform is possible after 'switching' that can
```sh
cd kotlin-project-dir
# switching to IntelliJ Idea 2019.1
bunch switch 191
# switching to IntelliJ Idea 2018.2
bunch switch . 182
```
## <a name="working-in-idea"></a> Working with the project in IntelliJ IDEA
Working with the Kotlin project requires at least IntelliJ IDEA 2019.1. You can download IntelliJ IDEA 2019.1 [here](https://www.jetbrains.com/idea/download).
Working with the Kotlin project requires at least IntelliJ IDEA 2017.3. You can download IntelliJ IDEA 2017.3 [here](https://www.jetbrains.com/idea/download).
After cloning the project, to import the project in Intellij choose the project directory in the Open project dialog. Then, after project opened, Select
`File` -> `New...` -> `Module from Existing Sources` in the menu, and select `build.gradle.kts` file in the project's root folder.
@@ -113,7 +113,7 @@ In the import dialog, select `use default gradle wrapper`.
To be able to run tests from IntelliJ easily, check `Delegate IDE build/run actions to Gradle` and choose `Gradle Test Runner` in the Gradle runner settings after importing the project.
At this time, you can use the latest released 1.3.x version of the Kotlin plugin for working with the code. To make sure you have the latest version installed, use Tools | Kotlin | Configure Kotlin Plugin Updates and press "Check for updates now".
At this time, you can use the latest released 1.2.x version of the Kotlin plugin for working with the code. To make sure you have the latest version installed, use Tools | Kotlin | Configure Kotlin Plugin Updates and press "Check for updates now".
### Compiling and running
@@ -125,20 +125,9 @@ From this root project there are Run/Debug Configurations for running IDEA or th
### Including into composite build
To include kotlin compiler into [composite build](https://docs.gradle.org/current/userguide/composite_builds.html) you need to define `dependencySubstitution` for `kotlin-compiler` module in `settings.gradle.kts`
To include kotlin compiler into [composite build](https://docs.gradle.org/current/userguide/composite_builds.html) you need to define `dependencySubstitution` for `kotlin-compiler` module in `settings.gradle`
```Kotlin
includeBuild("/path/to/kotlin") {
dependencySubstitution {
substitute(module("org.jetbrains.kotlin:kotlin-compiler"))
.with(project(":include:kotlin-compiler"))
}
}
```
or in `settings.gradle`
```Groovy
includeBuild('/path/to/kotlin') {
dependencySubstitution {
substitute module('org.jetbrains.kotlin:kotlin-compiler') with project(':include:kotlin-compiler')
@@ -146,9 +135,6 @@ includeBuild('/path/to/kotlin') {
}
```
# License
Kotlin is distributed under the terms of the Apache License (Version 2.0). See [license folder](license/README.md) for details.
# Contributing
Please be sure to review Kotlin's [contributing guidelines](docs/contributing.md) to learn how to help the project.

View File

@@ -1,97 +0,0 @@
import kotlinx.benchmark.gradle.benchmark
val benchmarks_version = "0.2.0-dev-7"
buildscript {
val benchmarks_version = "0.2.0-dev-7"
repositories {
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
if (cacheRedirectorEnabled) {
maven("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlinx")
maven("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-dev")
} else {
maven("https://dl.bintray.com/kotlin/kotlinx")
maven("https://dl.bintray.com/kotlin/kotlin-dev")
}
}
dependencies {
classpath("org.jetbrains.kotlinx:kotlinx.benchmark.gradle:$benchmarks_version")
}
}
apply(plugin = "kotlinx.benchmark")
plugins {
java
kotlin("jvm")
}
repositories {
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
if (cacheRedirectorEnabled) {
maven("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlinx")
maven("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-dev")
} else {
maven("https://dl.bintray.com/kotlin/kotlinx")
maven("https://dl.bintray.com/kotlin/kotlin-dev")
}
}
dependencies {
compile(kotlinStdlib())
compile(project(":compiler:frontend"))
compile(project(":compiler:cli"))
compile(intellijCoreDep()) { includeJars("intellij-core") }
compile(jpsStandalone()) { includeJars("jps-model") }
Platform[192].orHigher {
compile(intellijPluginDep("java"))
}
compile(intellijDep()) { includeIntellijCoreJarDependencies(project) }
compile("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:$benchmarks_version")
}
sourceSets {
"main" { projectDefault() }
}
benchmark {
configurations {
named("main") {
warmups = 10
iterations = 10
iterationTime = 1
iterationTimeUnit = "sec"
param("size", 1000)
}
register("fir") {
warmups = 10
iterations = 10
iterationTime = 1
iterationTimeUnit = "sec"
param("isIR", true)
param("size", 1000)
include("CommonCallsBenchmark")
//include("InferenceBaselineCallsBenchmark")
}
register("ni") {
warmups = 10
iterations = 10
iterationTime = 1
iterationTimeUnit = "sec"
param("useNI", true)
param("isIR", false)
param("size", 1000)
include("InferenceBaselineCallsBenchmark")
include("InferenceExplicitArgumentsCallsBenchmark")
include("InferenceForInApplicableCandidate")
include("InferenceFromArgumentCallsBenchmark")
include("InferenceFromReturnTypeCallsBenchmark")
}
}
targets {
register("main")
}
}

View File

@@ -1,19 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.Param
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
@State(Scope.Benchmark)
abstract class AbstractInferenceBenchmark : AbstractSimpleFileBenchmark() {
@Param("true", "false")
private var useNI: Boolean = false
override val useNewInference: Boolean
get() = useNI
}

View File

@@ -1,214 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import com.intellij.openapi.Disposable
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.impl.PsiFileFactoryImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.*
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.context.SimpleGlobalContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
import org.jetbrains.kotlin.fir.java.FirLibrarySession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.storage.ExceptionTracker
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.io.File
private fun createFile(shortName: String, text: String, project: Project): KtFile {
val virtualFile = object : LightVirtualFile(shortName, KotlinLanguage.INSTANCE, text) {
override fun getPath(): String {
//TODO: patch LightVirtualFile
return "/" + name
}
}
virtualFile.charset = CharsetToolkit.UTF8_CHARSET
val factory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
return factory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile
}
private val JDK_PATH = File("${System.getProperty("java.home")!!}/lib/rt.jar")
private val RUNTIME_JAR = File(System.getProperty("kotlin.runtime.path") ?: "dist/kotlinc/lib/kotlin-runtime.jar")
private val LANGUAGE_FEATURE_SETTINGS =
LanguageVersionSettingsImpl(
LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3,
specificFeatures = mapOf(LanguageFeature.NewInference to LanguageFeature.State.ENABLED)
)
private fun newConfiguration(useNewInference: Boolean): CompilerConfiguration {
val configuration = CompilerConfiguration()
configuration.put(CommonConfigurationKeys.MODULE_NAME, "benchmark")
configuration.put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, "../compiler/cli/cli-common/resources")
configuration.addJvmClasspathRoot(JDK_PATH)
configuration.addJvmClasspathRoot(RUNTIME_JAR)
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
val newInferenceState = if (useNewInference) LanguageFeature.State.ENABLED else LanguageFeature.State.DISABLED
configuration.languageVersionSettings = LanguageVersionSettingsImpl(
LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3,
specificFeatures = mapOf(
LanguageFeature.NewInference to newInferenceState
)
)
return configuration
}
@State(Scope.Benchmark)
abstract class AbstractSimpleFileBenchmark {
private var myDisposable: Disposable = Disposable { }
private lateinit var env: KotlinCoreEnvironment
private lateinit var file: KtFile
@Param("true", "false")
protected var isIR: Boolean = false
protected open val useNewInference get() = isIR
@Setup(Level.Trial)
fun setUp() {
if (isIR && !useNewInference) error("Invalid configuration")
env = KotlinCoreEnvironment.createForTests(
myDisposable,
newConfiguration(useNewInference),
EnvironmentConfigFiles.JVM_CONFIG_FILES
)
if (isIR) {
Extensions.getArea(env.project)
.getExtensionPoint(PsiElementFinder.EP_NAME)
.unregisterExtension(JavaElementFinder::class.java)
}
file = createFile(
"test.kt",
buildText(),
env.project
)
}
protected fun analyzeGreenFile(bh: Blackhole) {
if (isIR) {
analyzeGreenFileIr(bh)
} else {
analyzeGreenFileFrontend(bh)
}
}
private fun analyzeGreenFileFrontend(bh: Blackhole) {
val tracker = ExceptionTracker()
val storageManager: StorageManager =
LockBasedStorageManager.createWithExceptionHandling("benchmarks", tracker)
val context = SimpleGlobalContext(storageManager, tracker)
val module =
ModuleDescriptorImpl(
Name.special("<benchmark>"), storageManager,
JvmBuiltIns(storageManager, JvmBuiltIns.Kind.FROM_DEPENDENCIES)
)
val moduleContext = context.withProject(env.project).withModule(module)
val result = TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
moduleContext.project,
listOf(file),
NoScopeRecordCliBindingTrace(),
env.configuration,
{ scope -> JvmPackagePartProvider(LANGUAGE_FEATURE_SETTINGS, scope) }
)
assert(result.bindingContext.diagnostics.none { it.severity == Severity.ERROR })
bh.consume(result.shouldGenerateCode)
}
private fun analyzeGreenFileIr(bh: Blackhole) {
val scope = GlobalSearchScope.filesScope(env.project, listOf(file.virtualFile))
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(env.project))
val session = createSession(env, scope)
val firProvider = session.firProvider as FirProviderImpl
val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider, stubMode = false)
val totalTransformer = FirTotalResolveTransformer()
val firFile = builder.buildFirFile(file).also(firProvider::recordFile)
for (transformer in totalTransformer.transformers) {
transformer.transformFile(firFile, null)
}
bh.consume(firFile.hashCode())
}
protected abstract fun buildText(): String
}
fun createSession(
environment: KotlinCoreEnvironment,
sourceScope: GlobalSearchScope,
librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope)
): FirSession {
val moduleInfo = FirTestModuleInfo()
val project = environment.project
val provider = FirProjectSessionProvider(project)
return FirJavaModuleBasedSession(moduleInfo, provider, sourceScope).also {
createSessionForDependencies(provider, moduleInfo, librariesScope, environment)
}
}
private fun createSessionForDependencies(
provider: FirProjectSessionProvider,
moduleInfo: FirTestModuleInfo,
librariesScope: GlobalSearchScope,
environment: KotlinCoreEnvironment
) {
val dependenciesInfo = FirTestModuleInfo()
moduleInfo.dependencies.add(dependenciesInfo)
FirLibrarySession.create(
dependenciesInfo, provider, librariesScope, environment.project,
environment.createPackagePartProvider(librariesScope)
)
}
class FirTestModuleInfo(
override val name: Name = Name.identifier("TestModule"),
val dependencies: MutableList<ModuleInfo> = mutableListOf(),
override val platform: TargetPlatform = JvmPlatforms.unspecifiedJvmPlatform,
override val analyzerServices: PlatformDependentAnalyzerServices = JvmPlatformAnalyzerServices
) : ModuleInfo {
override fun dependencies(): List<ModuleInfo> = dependencies
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class CommonCallsBenchmark : AbstractSimpleFileBenchmark(){
@Param("1", "10", "100", "1000", "3000", "5000", "7000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun foo(): Int = 1
|
|fun bar() {
|${(1..size).joinToString("\n") { " foo()" }}
|}
""".trimMargin()
}

View File

@@ -1,42 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class ComplexDataFlowBenchmark : AbstractSimpleFileBenchmark(){
@Param("1", "100", "1000", "3000", "5000", "7000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|
|fun bar(x: Any?) {
| var y = x
|${(1..size).joinToString("\n") {
"""
|if (x is String) {
| y = x
|}
|y = 1
""".trimMargin()
}}
|}
""".trimMargin()
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class ControlFlowOperators : AbstractSimpleFileBenchmark(){
@Param("1", "100", "1000", "3000", "5000", "7000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|var isTrue = true
|var s = ""
|fun bar() {
|${(1..size).joinToString("\n") {
"""
|var x$it: String
|
|when (s) {
| "A" -> { x$it = "1" }
| "B" -> { x$it = "2" }
| else -> { x$it = "3" }
|}
|
|while (isTrue) {
| x$it.hashCode()
|}
""".trimMargin()
}}
|}
""".trimMargin()
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class InferenceBaselineCallsBenchmark : AbstractSimpleFileBenchmark() {
@Param("1", "10", "100", "1000", "5000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun foo(x: Int): Int = 1
|fun expectsInt(x: Int) {}
|fun bar(v: Int) {
|${(1..size).map { " expectsInt(foo(v))" }.joinToString("\n")}
|}
""".trimMargin()
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class InferenceExplicitArgumentsCallsBenchmark : AbstractInferenceBenchmark() {
@Param("1", "10", "100", "1000", "5000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun <T> foo(x: T): Int = 1
|fun expectsInt(x: Int) {}
|fun bar(v: Int) {
|${(1..size).map { " expectsInt(foo<Int>(v))" }.joinToString("\n")}
|}
""".trimMargin()
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class InferenceForInApplicableCandidate : AbstractInferenceBenchmark() {
@Param("1", "10", "100", "1000", "5000", "10000")
private var size: Int = 1
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun <T : Comparable<T>> foo(x: MutableList<T>) {}
|fun <T> foo(x: MutableList<T>, y: (T, T) -> Int) {}
|fun bar(x: MutableList<Any>) {
|${(1..size).joinToString("\n") { " foo(x) { a, b -> 1 }" }}
|}
""".trimMargin()
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class InferenceFromArgumentCallsBenchmark : AbstractInferenceBenchmark() {
@Param("1", "10", "100", "1000", "5000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun <T> foo(x: T): Int = 1
|fun expectsInt(x: Int) {}
|fun bar(v: Int) {
|${(1..size).map { " expectsInt(foo(v))" }.joinToString("\n")}
|}
""".trimMargin()
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class InferenceFromReturnTypeCallsBenchmark : AbstractInferenceBenchmark() {
@Param("1", "10", "100", "1000", "5000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun <T> foo(x: Int): T = null!!
|fun expectsInt(x: Int) {}
|fun bar(v: Int) {
|${(1..size).map { " expectsInt(foo(v))" }.joinToString("\n")}
|}
""".trimMargin()
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class IntArrayPlusBenchmark : AbstractSimpleFileBenchmark() {
@Param("1", "10", "100", "1000", "3000", "5000", "7000", "10000")
private var size: Int = 0
@Benchmark
//@Fork(jvmArgsAppend = ["-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"])
fun benchmark(bh: Blackhole) {
if (!isIR) error("Doesn't make sense to run it on old frontend on buildserver")
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun bar(x: IntArray, y: IntArray) {
|${(1..size).joinToString("\n") { " x + y" }}
|}
""".trimMargin()
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class ManyImplicitReceiversBenchmark : AbstractSimpleFileBenchmark() {
@Param("1", "10", "50")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText(): String {
return buildString {
appendln("inline fun <T, R> with(receiver: T, block: T.() -> R): R = block()")
for (i in 1..size) {
appendln("interface A$i {")
appendln(" fun foo$i()")
appendln("}")
appendln()
}
appendln()
append("fun test(")
append((1..size).joinToString(", ") { "a$it: A$it" })
appendln(" {")
for (i in 1..size) {
appendln("with(a$i) {")
}
for (i in 1..size) {
appendln("foo$i()")
}
for (i in 1..size) {
appendln("}")
}
appendln("}")
}
}
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class ManyValsBenchmark : AbstractSimpleFileBenchmark(){
@Param("1", "100", "1000", "3000", "5000", "7000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun bar() {
|${(1..size).joinToString("\n") { " val x$it: Int = 1" }}
|}
""".trimMargin()
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class ManyVarsBenchmark : AbstractSimpleFileBenchmark(){
@Param("1", "100", "1000", "3000", "5000", "7000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun bar() {
|${(1..size).joinToString("\n") { " var x$it: Int = 1" }}
|}
""".trimMargin()
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class SimpleDataFlowBenchmark : AbstractSimpleFileBenchmark(){
@Param("1", "100", "1000", "3000", "5000", "7000", "10000")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText() =
"""
|fun foo(x: Int): Int = 1
|var x = 1
|fun bar(v: Int) {
|${(1..size).joinToString("\n") { " x = foo(v)" }}
|}
""".trimMargin()
}

View File

@@ -1,3 +1,4 @@
description = "Kotlin Build Common"
plugins {
@@ -11,8 +12,7 @@ dependencies {
compileOnly(project(":compiler:cli-common"))
compileOnly(project(":compiler:frontend.java"))
compileOnly(project(":js:js.serializer"))
compileOnly(project(":js:js.config"))
compileOnly(project(":kotlin-util-klib-metadata"))
compileOnly(project(":js:js.frontend"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
compileOnly(intellijDep()) { includeJars("asm-all", "trove4j", "util", rootProject = rootProject) }
compileOnly(project(":kotlin-reflect-api"))
@@ -22,9 +22,8 @@ dependencies {
testCompile(commonDep("junit:junit"))
testCompile(protobufFull())
testCompile(kotlinStdlib())
Platform[193].orLower {
testCompileOnly(intellijDep()) { includeJars("openapi", rootProject = rootProject) }
}
testCompileOnly(intellijDep()) { includeJars("openapi") }
testRuntime(project(":kotlin-reflect"))
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,11 +22,9 @@ import org.jetbrains.kotlin.utils.sure
import java.io.File
open class GeneratedFile(
sourceFiles: Collection<File>,
val sourceFiles: Collection<File>,
val outputFile: File
) {
val sourceFiles = sourceFiles.sortedBy { it.path }
}
)
class GeneratedJvmClass (
sourceFiles: Collection<File>,

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.incremental
import com.intellij.util.io.DataExternalizer
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
import org.jetbrains.kotlin.incremental.js.IrTranslationResultValue
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
import org.jetbrains.kotlin.incremental.storage.*
import org.jetbrains.kotlin.metadata.ProtoBuf
@@ -29,7 +28,6 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
import org.jetbrains.kotlin.serialization.deserialization.getClassId
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
import java.io.DataInput
@@ -38,12 +36,10 @@ import java.io.File
open class IncrementalJsCache(
cachesDir: File,
pathConverter: FileToPathConverter,
serializerProtocol: SerializerExtensionProtocol
pathConverter: FileToPathConverter
) : AbstractIncrementalCache<FqName>(cachesDir, pathConverter) {
companion object {
private const val TRANSLATION_RESULT_MAP = "translation-result"
private const val IR_TRANSLATION_RESULT_MAP = "ir-translation-result"
private const val INLINE_FUNCTIONS = "inline-functions"
private const val HEADER_FILE_NAME = "header.meta"
private const val PACKAGE_META_FILE = "packages-meta"
@@ -51,12 +47,9 @@ open class IncrementalJsCache(
fun hasHeaderFile(cachesDir: File) = File(cachesDir, HEADER_FILE_NAME).exists()
}
private val protoData = ProtoDataProvider(serializerProtocol)
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile, pathConverter))
override val dirtyOutputClassesMap = registerMap(DirtyClassesFqNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile, pathConverter, protoData))
private val irTranslationResults = registerMap(IrTranslationResultMap(IR_TRANSLATION_RESULT_MAP.storageFile, pathConverter))
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile, pathConverter))
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile, pathConverter))
private val packageMetadata = registerMap(PackageMetadataMap(PACKAGE_META_FILE.storageFile))
@@ -83,17 +76,6 @@ open class IncrementalJsCache(
dirtySources.addAll(removedAndCompiledSources)
}
fun compare(translatedFiles: Map<File, TranslationResultValue>, changesCollector: ChangesCollector) {
for ((srcFile, data) in translatedFiles) {
val oldProtoMap = translationResults[srcFile]?.metadata?.let { protoData(srcFile, it) } ?: emptyMap()
val newProtoMap = protoData(srcFile, data.metadata)
for (classId in oldProtoMap.keys + newProtoMap.keys) {
changesCollector.collectProtoChanges(oldProtoMap[classId], newProtoMap[classId])
}
}
}
fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) {
val translatedFiles = incrementalResults.packageParts
@@ -101,8 +83,8 @@ open class IncrementalJsCache(
dirtySources.remove(srcFile)
val (binaryMetadata, binaryAst, inlineData) = data
val oldProtoMap = translationResults[srcFile]?.metadata?.let { protoData(srcFile, it) } ?: emptyMap()
val newProtoMap = protoData(srcFile, binaryMetadata)
val oldProtoMap = translationResults[srcFile]?.metadata?.let { getProtoData(srcFile, it) } ?: emptyMap()
val newProtoMap = getProtoData(srcFile, binaryMetadata)
for ((classId, protoData) in newProtoMap) {
registerOutputForFile(srcFile, classId.asSingleFqName())
@@ -126,11 +108,6 @@ open class IncrementalJsCache(
for ((packageName, metadata) in incrementalResults.packageMetadata) {
packageMetadata.put(packageName, metadata)
}
for ((srcFile, irData) in incrementalResults.irFileData) {
val (fileData, types, signatures, strings, declarations, bodies, fqn) = irData
irTranslationResults.put(srcFile, fileData, types, signatures, strings, declarations, bodies, fqn)
}
}
private fun registerOutputForFile(srcFile: File, name: FqName) {
@@ -141,7 +118,6 @@ open class IncrementalJsCache(
override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
dirtySources.forEach {
translationResults.remove(it, changesCollector)
irTranslationResults.remove(it)
inlineFunctions.remove(it)
}
removeAllFromClassStorage(dirtyOutputClassesMap.getDirtyOutputClasses(), changesCollector)
@@ -164,16 +140,6 @@ open class IncrementalJsCache(
put(fqNameString, packageMetadata[fqNameString]!!)
}
}
fun nonDirtyIrParts(): Map<File, IrTranslationResultValue> =
hashMapOf<File, IrTranslationResultValue>().apply {
for (file in irTranslationResults.keys()) {
if (file !in dirtySources) {
put(file, irTranslationResults[file]!!)
}
}
}
}
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
@@ -207,8 +173,7 @@ private object TranslationResultValueExternalizer : DataExternalizer<Translation
private class TranslationResultMap(
storageFile: File,
private val pathConverter: FileToPathConverter,
private val protoData: ProtoDataProvider
private val pathConverter: FileToPathConverter
) :
BasicStringMap<TranslationResultValue>(storageFile, TranslationResultValueExternalizer) {
override fun dumpValue(value: TranslationResultValue): String =
@@ -228,7 +193,7 @@ private class TranslationResultMap(
fun remove(sourceFile: File, changesCollector: ChangesCollector) {
val path = pathConverter.toPath(sourceFile)
val protoBytes = storage[path]!!.metadata
val protoMap = protoData(sourceFile, protoBytes)
val protoMap = getProtoData(sourceFile, protoBytes)
for ((_, protoData) in protoMap) {
changesCollector.collectProtoChanges(oldData = protoData, newData = null)
@@ -237,104 +202,6 @@ private class TranslationResultMap(
}
}
private object IrTranslationResultValueExternalizer : DataExternalizer<IrTranslationResultValue> {
override fun save(output: DataOutput, value: IrTranslationResultValue) {
output.writeArray(value.fileData)
output.writeArray(value.types)
output.writeArray(value.signatures)
output.writeArray(value.strings)
output.writeArray(value.declarations)
output.writeArray(value.bodies)
output.writeArray(value.fqn)
}
private fun DataOutput.writeArray(array: ByteArray) {
writeInt(array.size)
write(array)
}
private fun DataInput.readArray(): ByteArray {
val dataSize = readInt()
val filedata = ByteArray(dataSize)
readFully(filedata)
return filedata
}
override fun read(input: DataInput): IrTranslationResultValue {
val fileData = input.readArray()
val types = input.readArray()
val signatures = input.readArray()
val strings = input.readArray()
val declarations = input.readArray()
val bodies = input.readArray()
val fqn = input.readArray()
return IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn)
}
}
private class IrTranslationResultMap(
storageFile: File,
private val pathConverter: FileToPathConverter
) :
BasicStringMap<IrTranslationResultValue>(storageFile, IrTranslationResultValueExternalizer) {
override fun dumpValue(value: IrTranslationResultValue): String =
"Filedata: ${value.fileData.md5()}, " +
"Types: ${value.types.md5()}, " +
"Signatures: ${value.signatures.md5()}, " +
"Strings: ${value.strings.md5()}, " +
"Declarations: ${value.declarations.md5()}, " +
"Bodies: ${value.bodies.md5()}"
fun put(
sourceFile: File,
newFiledata: ByteArray,
newTypes: ByteArray,
newSignatures: ByteArray,
newStrings: ByteArray,
newDeclarations: ByteArray,
newBodies: ByteArray,
fqn: ByteArray
) {
storage[pathConverter.toPath(sourceFile)] =
IrTranslationResultValue(newFiledata, newTypes, newSignatures, newStrings, newDeclarations, newBodies, fqn)
}
operator fun get(sourceFile: File): IrTranslationResultValue? =
storage[pathConverter.toPath(sourceFile)]
fun keys(): Collection<File> =
storage.keys.map { pathConverter.toFile(it) }
fun remove(sourceFile: File) {
val path = pathConverter.toPath(sourceFile)
storage.remove(path)
}
}
private class ProtoDataProvider(private val serializerProtocol: SerializerExtensionProtocol) {
operator fun invoke(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData> {
val classes = hashMapOf<ClassId, ProtoData>()
val proto = ProtoBuf.PackageFragment.parseFrom(metadata, serializerProtocol.extensionRegistry)
val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
proto.class_List.forEach {
val classId = nameResolver.getClassId(it.fqName)
classes[classId] = ClassProtoData(it, nameResolver)
}
proto.`package`.apply {
val packageNameId = getExtensionOrNull(serializerProtocol.packageFqName)
val packageFqName = packageNameId?.let { FqName(nameResolver.getPackageFqName(it)) } ?: FqName.ROOT
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalize() + "Kt"))
classes[packagePartClassId] = PackagePartProtoData(this, nameResolver, packageFqName)
}
return classes
}
}
// TODO: remove this method once AbstractJsProtoComparisonTest is fixed
fun getProtoData(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData> {
val classes = hashMapOf<ClassId, ProtoData>()
val proto = ProtoBuf.PackageFragment.parseFrom(metadata, JsSerializerProtocol.extensionRegistry)

View File

@@ -55,13 +55,10 @@ class JavaClassesSerializerExtension : KotlinSerializerExtensionBase(BuiltInSeri
}
}
override fun serializeFunction(
descriptor: FunctionDescriptor,
proto: ProtoBuf.Function.Builder,
versionRequirementTable: MutableVersionRequirementTable?,
childSerializer: DescriptorSerializer
) {
super.serializeFunction(descriptor, proto, versionRequirementTable, childSerializer)
override fun serializeFunction(descriptor: FunctionDescriptor,
proto: ProtoBuf.Function.Builder,
childSerializer: DescriptorSerializer) {
super.serializeFunction(descriptor, proto, childSerializer)
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
proto.setExtension(JavaClassProtoBuf.isPackagePrivateMethod, true)
}

View File

@@ -75,13 +75,12 @@ open class LookupStorage(
}
@Synchronized
fun addAll(lookups: MultiMap<LookupSymbol, String>, allPaths: Set<String>) {
val pathToId = allPaths.sorted().keysToMap { addFileIfNeeded(File(it)) }
fun addAll(lookups: Set<Map.Entry<LookupSymbol, Collection<String>>>, allPaths: Set<String>) {
val pathToId = allPaths.keysToMap { addFileIfNeeded(File(it)) }
for (lookupSymbol in lookups.keySet().sorted()) {
for ((lookupSymbol, paths) in lookups) {
val key = LookupSymbolKey(lookupSymbol.name, lookupSymbol.scope)
val paths = lookups[lookupSymbol]!!
val fileIds = paths.mapTo(TreeSet()) { pathToId[it]!! }
val fileIds = paths.mapTo(HashSet<Int>()) { pathToId[it]!! }
fileIds.addAll(lookupMap[key] ?: emptySet())
lookupMap[key] = fileIds
}
@@ -228,11 +227,4 @@ class LookupTrackerImpl(private val delegate: LookupTracker) : LookupTracker {
}
}
data class LookupSymbol(val name: String, val scope: String) : Comparable<LookupSymbol> {
override fun compareTo(other: LookupSymbol): Int {
val scopeCompare = scope.compareTo(other.scope)
if (scopeCompare != 0) return scopeCompare
return name.compareTo(other.name)
}
}
data class LookupSymbol(val name: String, val scope: String)

View File

@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
import org.jetbrains.kotlin.synthetic.SAM_LOOKUP_NAME
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
import java.io.File
import java.util.*
@@ -126,7 +126,7 @@ fun LookupStorage.update(
removeLookupsFrom(filesToCompile.asSequence() + removedFiles.asSequence())
addAll(lookupTracker.lookups, lookupTracker.pathInterner.values)
addAll(lookupTracker.lookups.entrySet(), lookupTracker.pathInterner.values)
}
data class DirtyData(

View File

@@ -21,7 +21,4 @@ class IncrementalDataProviderFromCache(private val cache: IncrementalJsCache) :
override val packageMetadata: Map<String, ByteArray>
get() = cache.packageMetadata()
override val serializedIrFiles: Map<File, IrTranslationResultValue>
get() = cache.nonDirtyIrParts()
}

View File

@@ -30,9 +30,9 @@ import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
import java.util.*
data class Difference(
val isClassAffected: Boolean = false,
val areSubclassesAffected: Boolean = false,
val changedMembersNames: Set<String> = emptySet()
val isClassAffected: Boolean = false,
val areSubclassesAffected: Boolean = false,
val changedMembersNames: Set<String> = emptySet()
)
sealed class ProtoData
@@ -49,17 +49,14 @@ fun ProtoMapValue.toProtoData(packageFqName: FqName): ProtoData =
}
internal val MessageLite.isPrivate: Boolean
get() = Visibilities.isPrivate(
ProtoEnumFlags.visibility(
get() = Visibilities.isPrivate(ProtoEnumFlags.visibility(
when (this) {
is ProtoBuf.Constructor -> Flags.VISIBILITY.get(flags)
is ProtoBuf.Function -> Flags.VISIBILITY.get(flags)
is ProtoBuf.Property -> Flags.VISIBILITY.get(flags)
is ProtoBuf.TypeAlias -> Flags.VISIBILITY.get(flags)
else -> error("Unknown message: $this")
}
)
)
}))
private fun MessageLite.name(nameResolver: NameResolver): String {
return when (this) {
@@ -82,21 +79,9 @@ abstract class DifferenceCalculator {
val result = hashSetOf<String>()
val oldMap =
oldList.groupBy {
it.getHashCode(
compareObject::oldGetIndexOfString,
compareObject::oldGetIndexOfClassId,
compareObject::oldGetTypeById
)
}
oldList.groupBy { it.getHashCode({ compareObject.oldGetIndexOfString(it) }, { compareObject.oldGetIndexOfClassId(it) }) }
val newMap =
newList.groupBy {
it.getHashCode(
compareObject::newGetIndexOfString,
compareObject::newGetIndexOfClassId,
compareObject::newGetTypeById
)
}
newList.groupBy { it.getHashCode({ compareObject.newGetIndexOfString(it) }, { compareObject.newGetIndexOfClassId(it) }) }
val hashes = oldMap.keys + newMap.keys
for (hash in hashes) {
@@ -115,8 +100,8 @@ abstract class DifferenceCalculator {
}
private fun calcDifferenceForEqualHashes(
oldList: List<MessageLite>,
newList: List<MessageLite>
oldList: List<MessageLite>,
newList: List<MessageLite>
): Collection<String> {
val result = hashSetOf<String>()
val newSet = HashSet(newList)
@@ -125,7 +110,8 @@ abstract class DifferenceCalculator {
val newMember = newSet.firstOrNull { compareObject.checkEquals(oldMember, it) }
if (newMember != null) {
newSet.remove(newMember)
} else {
}
else {
result.add(oldMember.name(compareObject.oldNameResolver))
}
}
@@ -138,20 +124,20 @@ abstract class DifferenceCalculator {
}
protected fun calcDifferenceForNames(
oldList: List<Int>,
newList: List<Int>
oldList: List<Int>,
newList: List<Int>
): Collection<String> {
val oldNames = oldList.map { compareObject.oldNameResolver.getString(it) }.toSet()
val newNames = newList.map { compareObject.newNameResolver.getString(it) }.toSet()
return oldNames.union(newNames) - oldNames.intersect(newNames)
}
private fun MessageLite.getHashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int, typeTable: (Int) -> ProtoBuf.Type): Int {
private fun MessageLite.getHashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
return when (this) {
is ProtoBuf.Constructor -> hashCode(stringIndexes, fqNameIndexes, typeTable)
is ProtoBuf.Function -> hashCode(stringIndexes, fqNameIndexes, typeTable)
is ProtoBuf.Property -> hashCode(stringIndexes, fqNameIndexes, typeTable)
is ProtoBuf.TypeAlias -> hashCode(stringIndexes, fqNameIndexes, typeTable)
is ProtoBuf.Constructor -> hashCode(stringIndexes, fqNameIndexes)
is ProtoBuf.Function -> hashCode(stringIndexes, fqNameIndexes)
is ProtoBuf.Property -> hashCode(stringIndexes, fqNameIndexes)
is ProtoBuf.TypeAlias -> hashCode(stringIndexes, fqNameIndexes)
else -> error("Unknown message: $this")
}
}
@@ -168,15 +154,10 @@ abstract class DifferenceCalculator {
}
class DifferenceCalculatorForClass(
private val oldData: ClassProtoData,
private val newData: ClassProtoData
private val oldData: ClassProtoData,
private val newData: ClassProtoData
) : DifferenceCalculator() {
override val compareObject = ProtoCompareGenerated(
oldNameResolver = oldData.nameResolver,
newNameResolver = newData.nameResolver,
oldTypeTable = oldData.proto.typeTableOrNull,
newTypeTable = newData.proto.typeTableOrNull
)
override val compareObject = ProtoCompareGenerated(oldData.nameResolver, newData.nameResolver)
override fun difference(): Difference {
val (oldProto, oldNameResolver) = oldData
@@ -239,8 +220,11 @@ class DifferenceCalculatorForClass(
// when (x as Base) { is Impl -> ... }
areSubclassesAffected = true
}
ProtoBufClassKind.VERSION_REQUIREMENT_LIST,
ProtoBufClassKind.VERSION_REQUIREMENT_TABLE -> {
ProtoBufClassKind.TYPE_TABLE -> {
// TODO
}
ProtoCompareGenerated.ProtoBufClassKind.VERSION_REQUIREMENT_LIST,
ProtoCompareGenerated.ProtoBufClassKind.VERSION_REQUIREMENT_TABLE -> {
// TODO
}
ProtoBufClassKind.FLAGS,
@@ -254,7 +238,7 @@ class DifferenceCalculatorForClass(
}
ProtoBufClassKind.JVM_EXT_CLASS_MODULE_NAME,
ProtoBufClassKind.JS_EXT_CLASS_CONTAINING_FILE_ID -> {
// TODO
// TODO
}
ProtoBufClassKind.JVM_EXT_CLASS_LOCAL_VARIABLE_LIST -> {
// Not affected, local variables are not accessible outside of a file
@@ -266,13 +250,9 @@ class DifferenceCalculatorForClass(
ProtoBufClassKind.BUILT_INS_EXT_CLASS_ANNOTATION_LIST -> {
isClassAffected = true
}
ProtoBufClassKind.JVM_EXT_ANONYMOUS_OBJECT_ORIGIN_NAME -> {
ProtoCompareGenerated.ProtoBufClassKind.JVM_EXT_ANONYMOUS_OBJECT_ORIGIN_NAME -> {
// Not affected, this extension is not used in the compiler
}
ProtoBufClassKind.KLIB_EXT_CLASS_ANNOTATION_LIST -> {
isClassAffected = true
areSubclassesAffected = true
}
}
}
@@ -281,15 +261,10 @@ class DifferenceCalculatorForClass(
}
class DifferenceCalculatorForPackageFacade(
private val oldData: PackagePartProtoData,
private val newData: PackagePartProtoData
private val oldData: PackagePartProtoData,
private val newData: PackagePartProtoData
) : DifferenceCalculator() {
override val compareObject = ProtoCompareGenerated(
oldNameResolver = oldData.nameResolver,
newNameResolver = newData.nameResolver,
oldTypeTable = oldData.proto.typeTableOrNull,
newTypeTable = newData.proto.typeTableOrNull
)
override val compareObject = ProtoCompareGenerated(oldData.nameResolver, newData.nameResolver)
override fun difference(): Difference {
val oldProto = oldData.proto
@@ -314,9 +289,10 @@ class DifferenceCalculatorForPackageFacade(
names.addAll(calcDifferenceForNonPrivateMembers(ProtoBuf.Package::getPropertyList))
ProtoBufPackageKind.TYPE_ALIAS_LIST ->
names.addAll(calcDifferenceForNonPrivateMembers(ProtoBuf.Package::getTypeAliasList))
ProtoBufPackageKind.TYPE_TABLE,
ProtoBufPackageKind.VERSION_REQUIREMENT_TABLE,
ProtoBufPackageKind.JVM_EXT_PACKAGE_MODULE_NAME,
ProtoBufPackageKind.JS_EXT_PACKAGE_FQ_NAME -> {
ProtoBufPackageKind.JS_EXT_PACKAGE_FQ_NAME-> {
// TODO
}
ProtoBufPackageKind.JVM_EXT_PACKAGE_LOCAL_VARIABLE_LIST -> {
@@ -325,9 +301,6 @@ class DifferenceCalculatorForPackageFacade(
ProtoBufPackageKind.BUILT_INS_EXT_PACKAGE_FQ_NAME -> {
// Not affected
}
ProtoBufPackageKind.KLIB_EXT_PACKAGE_FQ_NAME -> {
// Not affected
}
}
}
@@ -337,9 +310,3 @@ class DifferenceCalculatorForPackageFacade(
private val ProtoBuf.Class.isSealed: Boolean
get() = ProtoBuf.Modality.SEALED == Flags.MODALITY.get(flags)
val ProtoBuf.Class.typeTableOrNull: ProtoBuf.TypeTable?
get() = if (hasTypeTable()) typeTable else null
val ProtoBuf.Package.typeTableOrNull: ProtoBuf.TypeTable?
get() = if (hasTypeTable()) typeTable else null

View File

@@ -24,20 +24,11 @@ import org.jetbrains.kotlin.utils.Printer
import java.io.File
abstract class BasicMap<K : Comparable<K>, V>(
internal val storageFile: File,
storageFile: File,
keyDescriptor: KeyDescriptor<K>,
valueExternalizer: DataExternalizer<V>
) {
protected val storage: LazyStorage<K, V>
private val nonCachingStorage = System.getProperty("kotlin.jps.non.caching.storage")?.toBoolean() ?: false
init {
storage = if (nonCachingStorage) {
NonCachingLazyStorage(storageFile, keyDescriptor, valueExternalizer)
} else {
CachingLazyStorage(storageFile, keyDescriptor, valueExternalizer)
}
}
protected val storage = LazyStorage(storageFile, keyDescriptor, valueExternalizer)
fun clean() {
storage.clean()

View File

@@ -1,81 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.EnumeratorStringDescriptor
import com.intellij.util.io.KeyDescriptor
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.utils.Printer
import java.io.File
abstract class BasicMap<K : Comparable<K>, V>(
internal val storageFile: File,
keyDescriptor: KeyDescriptor<K>,
valueExternalizer: DataExternalizer<V>
) {
protected val storage = LazyStorage(storageFile, keyDescriptor, valueExternalizer)
fun clean() {
storage.clean()
}
fun flush(memoryCachesOnly: Boolean) {
storage.flush(memoryCachesOnly)
}
fun close() {
storage.close()
}
@TestOnly
fun dump(): String {
return with(StringBuilder()) {
with(Printer(this)) {
println(this@BasicMap::class.java.simpleName)
pushIndent()
for (key in storage.keys.sorted()) {
println("${dumpKey(key)} -> ${dumpValue(storage[key]!!)}")
}
popIndent()
}
this
}.toString()
}
@TestOnly
protected abstract fun dumpKey(key: K): String
@TestOnly
protected abstract fun dumpValue(value: V): String
}
abstract class BasicStringMap<V>(
storageFile: File,
keyDescriptor: KeyDescriptor<String>,
valueExternalizer: DataExternalizer<V>
) : BasicMap<String, V>(storageFile, keyDescriptor, valueExternalizer) {
constructor(
storageFile: File,
valueExternalizer: DataExternalizer<V>
) : this(storageFile, EnumeratorStringDescriptor.INSTANCE, valueExternalizer)
override fun dumpKey(key: String): String = key
}

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.incremental.storage
import org.jetbrains.annotations.TestOnly
import java.io.File
import java.io.IOException
open class BasicMapsOwner(val cachesDir: File) {
private val maps = arrayListOf<BasicMap<*, *>>()
@@ -36,35 +35,16 @@ open class BasicMapsOwner(val cachesDir: File) {
}
open fun clean() {
forEachMapSafe("clean", BasicMap<*, *>::clean)
maps.forEach { it.clean() }
}
open fun close() {
forEachMapSafe("close", BasicMap<*, *>::close)
maps.forEach { it.close() }
}
open fun flush(memoryCachesOnly: Boolean) {
forEachMapSafe("flush") { it.flush(memoryCachesOnly) }
maps.forEach { it.flush(memoryCachesOnly) }
}
private fun forEachMapSafe(actionName: String, action: (BasicMap<*, *>) -> Unit) {
val actionExceptions = LinkedHashMap<String, Exception>()
maps.forEach {
try {
action(it)
} catch (e: Exception) {
actionExceptions[it.storageFile.name] = e
}
}
if (actionExceptions.isNotEmpty()) {
val desc = "Could not $actionName incremental caches in $cachesDir: ${actionExceptions.keys.joinToString(", ")}"
val allIOExceptions = actionExceptions.all { it is IOException }
val ex = if (allIOExceptions) IOException(desc) else Exception(desc)
actionExceptions.forEach { (_, e) -> ex.addSuppressed(e) }
throw ex
}
}
@TestOnly
fun dump(): String = maps.joinToString("\n\n") { it.dump() }
@TestOnly fun dump(): String = maps.joinToString("\n\n") { it.dump() }
}

View File

@@ -1,107 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.KeyDescriptor
import com.intellij.util.io.PersistentHashMap
import java.io.File
/**
* It's lazy in a sense that PersistentHashMap is created only on write
*/
class CachingLazyStorage<K, V>(
private val storageFile: File,
private val keyDescriptor: KeyDescriptor<K>,
private val valueExternalizer: DataExternalizer<V>
) : LazyStorage<K, V> {
@Volatile
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
if (storageFile.exists()) {
storage = createMap()
return storage
}
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
override val keys: Collection<K>
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendData(key, { valueExternalizer.save(it, value) })
}
@Synchronized
override fun clean() {
try {
storage?.close()
} finally {
PersistentHashMap.deleteFilesStartingWith(storageFile)
storage = null
}
}
@Synchronized
override fun flush(memoryCachesOnly: Boolean) {
val existingStorage = storage ?: return
if (memoryCachesOnly) {
if (existingStorage.isDirty) {
existingStorage.dropMemoryCaches()
}
} else {
existingStorage.force()
}
}
@Synchronized
override fun close() {
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> = PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
}

View File

@@ -26,7 +26,7 @@ internal open class ClassOneToManyMap(
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
fun add(key: FqName, value: FqName) {
storage.append(key.asString(), listOf(value.asString()))
storage.append(key.asString(), value.asString())
}
operator fun get(key: FqName): Collection<FqName> =

View File

@@ -1,55 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import org.jetbrains.kotlin.incremental.dumpCollection
import org.jetbrains.kotlin.name.FqName
import java.io.File
internal open class ClassOneToManyMap(
storageFile: File
) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
fun add(key: FqName, value: FqName) {
storage.append(key.asString(), value.asString())
}
operator fun get(key: FqName): Collection<FqName> =
storage[key.asString()]?.map(::FqName) ?: setOf()
operator fun set(key: FqName, values: Collection<FqName>) {
if (values.isEmpty()) {
remove(key)
return
}
storage[key.asString()] = values.map(FqName::asString)
}
fun remove(key: FqName) {
storage.remove(key.asString())
}
fun removeValues(key: FqName, removed: Set<FqName>) {
val notRemoved = this[key].filter { it !in removed }
this[key] = notRemoved
}
}
internal class SubtypesMap(storageFile: File) : ClassOneToManyMap(storageFile)
internal class SupertypesMap(storageFile: File) : ClassOneToManyMap(storageFile)

View File

@@ -16,14 +16,107 @@
package org.jetbrains.kotlin.incremental.storage
interface LazyStorage<K, V> {
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.IOUtil
import com.intellij.util.io.KeyDescriptor
import com.intellij.util.io.PersistentHashMap
import java.io.DataOutput
import java.io.File
import java.io.IOException
/**
* It's lazy in a sense that PersistentHashMap is created only on write
*/
class LazyStorage<K, V>(
private val storageFile: File,
private val keyDescriptor: KeyDescriptor<K>,
private val valueExternalizer: DataExternalizer<V>
) {
@Volatile
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
if (storageFile.exists()) {
storage = createMap()
return storage
}
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
val keys: Collection<K>
operator fun contains(key: K): Boolean
operator fun get(key: K): V?
operator fun set(key: K, value: V)
fun remove(key: K)
fun append(key: K, value: V)
fun clean()
fun flush(memoryCachesOnly: Boolean)
fun close()
}
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
fun append(key: K, value: String) {
append(key) { out -> IOUtil.writeUTF(out, value) }
}
fun append(key: K, value: Int) {
append(key) { out -> out.writeInt(value) }
}
@Synchronized
fun clean() {
try {
storage?.close()
}
catch (ignored: Throwable) {
}
PersistentHashMap.deleteFilesStartingWith(storageFile)
storage = null
}
@Synchronized
fun flush(memoryCachesOnly: Boolean) {
val existingStorage = storage ?: return
if (memoryCachesOnly) {
if (existingStorage.isDirty) {
existingStorage.dropMemoryCaches()
}
}
else {
existingStorage.force()
}
}
@Synchronized
fun close() {
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> =
PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
private fun append(key: K, append: (DataOutput)->Unit) {
getStorageOrCreateNew().appendData(key, append)
}
}

View File

@@ -1,122 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.IOUtil
import com.intellij.util.io.KeyDescriptor
import com.intellij.util.io.PersistentHashMap
import java.io.DataOutput
import java.io.File
import java.io.IOException
/**
* It's lazy in a sense that PersistentHashMap is created only on write
*/
class LazyStorage<K, V>(
private val storageFile: File,
private val keyDescriptor: KeyDescriptor<K>,
private val valueExternalizer: DataExternalizer<V>
) {
@Volatile
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
if (storageFile.exists()) {
storage = createMap()
return storage
}
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
val keys: Collection<K>
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
fun append(key: K, value: String) {
append(key) { out -> IOUtil.writeUTF(out, value) }
}
fun append(key: K, value: Int) {
append(key) { out -> out.writeInt(value) }
}
@Synchronized
fun clean() {
try {
storage?.close()
}
catch (ignored: Throwable) {
}
PersistentHashMap.deleteFilesStartingWith(storageFile)
storage = null
}
@Synchronized
fun flush(memoryCachesOnly: Boolean) {
val existingStorage = storage ?: return
if (memoryCachesOnly) {
if (existingStorage.isDirty) {
existingStorage.dropMemoryCaches()
}
}
else {
existingStorage.force()
}
}
@Synchronized
fun close() {
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> =
PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
private fun append(key: K, append: (DataOutput)->Unit) {
getStorageOrCreateNew().appendData(key, append)
}
}

View File

@@ -24,7 +24,7 @@ internal class LookupMap(storage: File) : BasicMap<LookupSymbolKey, Collection<I
override fun dumpValue(value: Collection<Int>): String = value.toString()
fun add(name: String, scope: String, fileId: Int) {
storage.append(LookupSymbolKey(name, scope), listOf(fileId))
storage.append(LookupSymbolKey(name, scope), fileId)
}
operator fun get(key: LookupSymbolKey): Collection<Int>? = storage[key]

View File

@@ -1,42 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import java.io.File
internal class LookupMap(storage: File) : BasicMap<LookupSymbolKey, Collection<Int>>(storage, LookupSymbolKeyDescriptor, IntCollectionExternalizer) {
override fun dumpKey(key: LookupSymbolKey): String = key.toString()
override fun dumpValue(value: Collection<Int>): String = value.toString()
fun add(name: String, scope: String, fileId: Int) {
storage.append(LookupSymbolKey(name, scope), fileId)
}
operator fun get(key: LookupSymbolKey): Collection<Int>? = storage[key]
operator fun set(key: LookupSymbolKey, fileIds: Set<Int>) {
storage[key] = fileIds
}
fun remove(key: LookupSymbolKey) {
storage.remove(key)
}
val keys: Collection<LookupSymbolKey>
get() = storage.keys
}

View File

@@ -1,106 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.KeyDescriptor
import com.intellij.util.io.JpsPersistentHashMap
import java.io.File
class NonCachingLazyStorage<K, V>(
private val storageFile: File,
private val keyDescriptor: KeyDescriptor<K>,
private val valueExternalizer: DataExternalizer<V>
) : LazyStorage<K, V> {
@Volatile
private var storage: JpsPersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): JpsPersistentHashMap<K, V>? {
if (storage != null) return storage
if (storageFile.exists()) {
storage = createMap()
return storage
}
return null
}
@Synchronized
private fun getStorageOrCreateNew(): JpsPersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
override val keys: Collection<K>
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendDataWithoutCache(key, value)
}
@Synchronized
override fun clean() {
try {
storage?.close()
} catch (ignored: Throwable) {
}
JpsPersistentHashMap.deleteFilesStartingWith(storageFile)
storage = null
}
@Synchronized
override fun flush(memoryCachesOnly: Boolean) {
val existingStorage = storage ?: return
if (memoryCachesOnly) {
if (existingStorage.isDirty) {
existingStorage.dropMemoryCaches()
}
} else {
existingStorage.force()
}
}
@Synchronized
override fun close() {
storage?.close()
}
private fun createMap(): JpsPersistentHashMap<K, V> =
JpsPersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
}

View File

@@ -1,106 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.KeyDescriptor
import com.intellij.util.io.PersistentHashMap
import java.io.File
class NonCachingLazyStorage<K, V>(
private val storageFile: File,
private val keyDescriptor: KeyDescriptor<K>,
private val valueExternalizer: DataExternalizer<V>
) : LazyStorage<K, V> {
@Volatile
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
if (storageFile.exists()) {
storage = createMap()
return storage
}
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
override val keys: Collection<K>
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendData(key) { dataOutput -> valueExternalizer.save(dataOutput, value) }
}
@Synchronized
override fun clean() {
try {
storage?.close()
} catch (ignored: Throwable) {
}
PersistentHashMap.deleteFilesStartingWith(storageFile)
storage = null
}
@Synchronized
override fun flush(memoryCachesOnly: Boolean) {
val existingStorage = storage ?: return
if (memoryCachesOnly) {
if (existingStorage.isDirty) {
existingStorage.dropMemoryCaches()
}
} else {
existingStorage.force()
}
}
@Synchronized
override fun close() {
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> =
PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.storage
import java.io.File
open class RelativeFileToPathConverter(baseDirFile: File?) : FileToPathConverter {
private val baseDirPath = baseDirFile?.canonicalFile?.invariantSeparatorsPath
override fun toPath(file: File): String {
val path = file.canonicalFile.invariantSeparatorsPath
return when {
baseDirPath != null && path.startsWith(baseDirPath) ->
PROJECT_DIR_PLACEHOLDER + path.substring(baseDirPath.length)
else -> path
}
}
override fun toFile(path: String): File =
when {
path.startsWith(PROJECT_DIR_PLACEHOLDER) -> {
val basePath = baseDirPath ?: error("Could not get project root dir")
File(basePath + path.substring(PROJECT_DIR_PLACEHOLDER.length))
}
else -> File(path)
}
private companion object {
private const val PROJECT_DIR_PLACEHOLDER = "${'$'}PROJECT_DIR$"
}
}

View File

@@ -41,7 +41,7 @@ internal abstract class AbstractSourceToOutputMap<Name>(
}
fun add(sourceFile: File, className: Name) {
storage.append(pathConverter.toPath(sourceFile), listOf(nameTransformer.asString(className)))
storage.append(pathConverter.toPath(sourceFile), nameTransformer.asString(className))
}
fun contains(sourceFile: File): Boolean =

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.storage
import org.jetbrains.kotlin.incremental.dumpCollection
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
internal class SourceToJvmNameMap(
storageFile: File,
pathConverter: FileToPathConverter
) : AbstractSourceToOutputMap<JvmClassName>(JvmClassNameTransformer, storageFile, pathConverter)
internal class SourceToFqNameMap(
storageFile: File,
pathConverter: FileToPathConverter
) : AbstractSourceToOutputMap<FqName>(FqNameTransformer, storageFile, pathConverter)
internal abstract class AbstractSourceToOutputMap<Name>(
private val nameTransformer: NameTransformer<Name>,
storageFile: File,
private val pathConverter: FileToPathConverter
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
fun clearOutputsForSource(sourceFile: File) {
remove(pathConverter.toPath(sourceFile))
}
fun add(sourceFile: File, className: Name) {
storage.append(pathConverter.toPath(sourceFile), nameTransformer.asString(className))
}
fun contains(sourceFile: File): Boolean =
pathConverter.toPath(sourceFile) in storage
operator fun get(sourceFile: File): Collection<Name> =
storage[pathConverter.toPath(sourceFile)].orEmpty().map(nameTransformer::asName)
fun getFqNames(sourceFile: File): Collection<FqName> =
storage[pathConverter.toPath(sourceFile)].orEmpty().map(nameTransformer::asFqName)
override fun dumpValue(value: Collection<String>) =
value.dumpCollection()
private fun remove(path: String) {
storage.remove(path)
}
}

View File

@@ -1,90 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.storage
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.TestWithWorkingDir
import org.jetbrains.kotlin.incremental.LookupStorage
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
import org.junit.Test
import java.io.File
class RelocatableCachesTest : TestWithWorkingDir() {
@Test
fun testLookupStorageAddAllReversedFiles() {
val originalRoot = workingDir.resolve("original")
fillLookupStorage(originalRoot, reverseFiles = false, reverseLookups = false)
val reversedFilesOrderRoot = workingDir.resolve("reversedFiles")
fillLookupStorage(reversedFilesOrderRoot, reverseFiles = true, reverseLookups = false)
assertEqualDirectories(originalRoot, reversedFilesOrderRoot, forgiveExtraFiles = false)
}
@Test
fun testLookupStorageAddAllReversedLookups() {
val originalRoot = workingDir.resolve("original")
fillLookupStorage(originalRoot, reverseFiles = false, reverseLookups = false)
val reversedLookupsOrderRoot = workingDir.resolve("reversedLookups")
fillLookupStorage(reversedLookupsOrderRoot, reverseFiles = false, reverseLookups = true)
assertEqualDirectories(originalRoot, reversedLookupsOrderRoot, forgiveExtraFiles = false)
}
@Test
fun testLookupStorageAddAllReversedFilesReversedLookups() {
val originalRoot = workingDir.resolve("original")
fillLookupStorage(originalRoot, reverseFiles = false, reverseLookups = false)
val reversedFilesReversedLookupsOrderRoot = workingDir.resolve("reversedFilesReversedLookupsOrderRoot")
fillLookupStorage(reversedFilesReversedLookupsOrderRoot, reverseFiles = true, reverseLookups = true)
assertEqualDirectories(originalRoot, reversedFilesReversedLookupsOrderRoot, forgiveExtraFiles = false)
}
/**
* Fills lookup storage in [projectRoot] with N fq-names,
* where i_th fq-name myscope_i.MyClass_i has lookups for previous fq-names (from 0 to i-1)
*/
private fun fillLookupStorage(projectRoot: File, reverseFiles: Boolean, reverseLookups: Boolean) {
val storageRoot = projectRoot.storageRoot
val fileToPathConverter = RelativeFileToPathConverter(projectRoot)
val lookupStorage = LookupStorage(storageRoot, fileToPathConverter)
val files = LinkedHashSet<String>()
val symbols = LinkedHashSet<LookupSymbol>()
val lookups = MultiMap.createOrderedSet<LookupSymbol, String>()
for (i in 0..10) {
val newSymbol = LookupSymbol(name = "MyClass_$i", scope = "myscope_$i")
val newSourcePath = projectRoot.resolve("src/${newSymbol.asRelativePath()}").canonicalFile.invariantSeparatorsPath
symbols.add(newSymbol)
for (lookedUpSymbol in symbols) {
lookups.putValue(lookedUpSymbol, newSourcePath)
}
files.add(newSourcePath)
}
val filesToAdd = if (reverseFiles) files.reversedSet() else files
val lookupsToAdd = if (reverseLookups) lookups.reversedMultiMap() else lookups
lookupStorage.addAll(lookupsToAdd, filesToAdd)
lookupStorage.flush(memoryCachesOnly = false)
}
private val File.storageRoot: File
get() = resolve("storage")
private fun <K, V> MultiMap<K, V>.reversedMultiMap(): MultiMap<K, V> {
val newMap = MultiMap.createOrderedSet<K, V>()
for ((key, values) in entrySet().reversedSet()) {
newMap.putValues(key, values.reversed())
}
return newMap
}
private fun <T> Set<T>.reversedSet(): LinkedHashSet<T> =
reversed().toCollection(LinkedHashSet(size))
private fun LookupSymbol.asRelativePath(): String =
if (scope.isBlank()) name else scope.replace('.', '/') + '/' + name
}

View File

@@ -19,16 +19,12 @@ package org.jetbrains.kotlin.incremental.testingUtils
import java.io.File
data class BuildLogFinder(
private val isDataContainerBuildLogEnabled: Boolean = false,
private val isGradleEnabled: Boolean = false,
private val isJsEnabled: Boolean = false,
private val isJsIrEnabled: Boolean = false, // TODO rename as it is used for metadata-only test
private val isScopeExpansionEnabled: Boolean = false
private val isDataContainerBuildLogEnabled: Boolean = false,
private val isGradleEnabled: Boolean = false,
private val isJsEnabled: Boolean = false
) {
companion object {
private const val JS_LOG = "js-build.log"
private const val JS_IR_LOG = "js-ir-build.log"
private const val SCOPE_EXPANDING_LOG = "build-with-scope-expansion.log"
private const val GRADLE_LOG = "gradle-build.log"
private const val DATA_CONTAINER_LOG = "data-container-version-build.log"
const val JS_JPS_LOG = "js-jps-build.log"
@@ -42,8 +38,6 @@ data class BuildLogFinder(
val names = dir.list() ?: arrayOf()
val files = names.filter { File(dir, it).isFile }.toSet()
val matchedName = when {
isScopeExpansionEnabled && SCOPE_EXPANDING_LOG in files -> SCOPE_EXPANDING_LOG
isJsIrEnabled && JS_IR_LOG in files -> JS_IR_LOG
isJsEnabled && JS_LOG in files -> JS_LOG
isGradleEnabled && GRADLE_LOG in files -> GRADLE_LOG
isJsEnabled && JS_JPS_LOG in files -> JS_JPS_LOG

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.incremental.testingUtils
import com.intellij.openapi.util.io.FileUtil
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapError
import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapParser
@@ -36,7 +37,6 @@ import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.util.TraceClassVisitor
import org.junit.Assert
import org.junit.Assert.assertNotNull
import org.junit.ComparisonFailure
import java.io.*
import java.util.*
import java.util.zip.CRC32
@@ -72,15 +72,7 @@ fun assertEqualDirectories(expected: File, actual: File, forgiveExtraFiles: Bool
}
}
if (expectedString != actualString) {
val message: String? = null
throw ComparisonFailure(
message,
expectedString.replaceFirst(DIR_ROOT_PLACEHOLDER, expected.canonicalPath),
actualString.replaceFirst(DIR_ROOT_PLACEHOLDER, actual.canonicalPath)
)
}
Assert.assertEquals(expectedString, actualString)
}
private fun File.checksumString(): String {
@@ -89,8 +81,6 @@ private fun File.checksumString(): String {
return java.lang.Long.toHexString(crc32.value)
}
private const val DIR_ROOT_PLACEHOLDER = "<DIR_ROOT_PLACEHOLDER>"
private fun getDirectoryString(dir: File, interestingPaths: List<String>): String {
val buf = StringBuilder()
val p = Printer(buf)
@@ -119,7 +109,7 @@ private fun getDirectoryString(dir: File, interestingPaths: List<String>): Strin
}
p.println(DIR_ROOT_PLACEHOLDER)
p.println(".")
addDirContent(dir)
for (path in interestingPaths) {

View File

@@ -11,8 +11,6 @@ public final class DebugExtOptionsProtoBuf {
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.stringIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.skipMessageInComparison);
}
public static final int SKIP_IN_COMPARISON_FIELD_NUMBER = 50000;
/**
@@ -58,28 +56,6 @@ public final class DebugExtOptionsProtoBuf {
.newFileScopedGeneratedExtension(
java.lang.Boolean.class,
null);
public static final int TYPE_ID_IN_TABLE_FIELD_NUMBER = 50004;
/**
* <code>extend .google.protobuf.FieldOptions { ... }</code>
*/
public static final
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
org.jetbrains.kotlin.protobuf.DescriptorProtos.FieldOptions,
java.lang.Boolean> typeIdInTable = org.jetbrains.kotlin.protobuf.GeneratedMessage
.newFileScopedGeneratedExtension(
java.lang.Boolean.class,
null);
public static final int SKIP_MESSAGE_IN_COMPARISON_FIELD_NUMBER = 50100;
/**
* <code>extend .google.protobuf.MessageOptions { ... }</code>
*/
public static final
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
org.jetbrains.kotlin.protobuf.DescriptorProtos.MessageOptions,
java.lang.Boolean> skipMessageInComparison = org.jetbrains.kotlin.protobuf.GeneratedMessage
.newFileScopedGeneratedExtension(
java.lang.Boolean.class,
null);
public static org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor
getDescriptor() {
@@ -97,11 +73,8 @@ public final class DebugExtOptionsProtoBuf {
"rotobuf.FieldOptions\030\321\206\003 \001(\010:<\n\023fq_name_" +
"id_in_table\022\035.google.protobuf.FieldOptio" +
"ns\030\322\206\003 \001(\010:;\n\022string_id_in_table\022\035.googl" +
"e.protobuf.FieldOptions\030\323\206\003 \001(\010:9\n\020type_" +
"id_in_table\022\035.google.protobuf.FieldOptio",
"ns\030\324\206\003 \001(\010:E\n\032skip_message_in_comparison" +
"\022\037.google.protobuf.MessageOptions\030\264\207\003 \001(" +
"\010B\031B\027DebugExtOptionsProtoBuf"
"e.protobuf.FieldOptions\030\323\206\003 \001(\010B\031B\027Debug" +
"ExtOptionsProtoBuf"
};
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
@@ -120,8 +93,6 @@ public final class DebugExtOptionsProtoBuf {
nameIdInTable.internalInit(descriptor.getExtensions().get(1));
fqNameIdInTable.internalInit(descriptor.getExtensions().get(2));
stringIdInTable.internalInit(descriptor.getExtensions().get(3));
typeIdInTable.internalInit(descriptor.getExtensions().get(4));
skipMessageInComparison.internalInit(descriptor.getExtensions().get(5));
org.jetbrains.kotlin.protobuf.DescriptorProtos.getDescriptor();
}

View File

@@ -10100,7 +10100,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
boolean hasFlags();
@@ -10117,7 +10116,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
int getFlags();
@@ -10855,7 +10853,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public boolean hasFlags() {
@@ -10874,7 +10871,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public int getFlags() {
@@ -12246,7 +12242,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public boolean hasFlags() {
@@ -12265,7 +12260,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public int getFlags() {
@@ -12284,7 +12278,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public Builder setFlags(int value) {
@@ -12306,7 +12299,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public Builder clearFlags() {
@@ -34310,194 +34302,192 @@ public final class DebugProtoBuf {
java.lang.String[] descriptorData = {
"\n&core/metadata/src/metadata.debug.proto" +
"\022\035org.jetbrains.kotlin.metadata\032)core/me" +
"tadata/src/ext_options.debug.proto\"#\n\013St" +
"ringTable\022\016\n\006string\030\001 \003(\t:\004\240\273\030\001\"\304\002\n\022Qual" +
"ifiedNameTable\022W\n\016qualified_name\030\001 \003(\0132?" +
".org.jetbrains.kotlin.metadata.Qualified" +
"NameTable.QualifiedName\032\316\001\n\rQualifiedNam" +
"e\022!\n\025parent_qualified_name\030\001 \001(\005:\002-1\022\022\n\n" +
"short_name\030\002 \002(\005\022[\n\004kind\030\003 \001(\0162D.org.jet" +
"brains.kotlin.metadata.QualifiedNameTabl",
"e.QualifiedName.Kind:\007PACKAGE\")\n\004Kind\022\t\n" +
"\005CLASS\020\000\022\013\n\007PACKAGE\020\001\022\t\n\005LOCAL\020\002:\004\240\273\030\001\"\226" +
"\006\n\nAnnotation\022\020\n\002id\030\001 \002(\005B\004\220\265\030\001\022D\n\010argum" +
"ent\030\002 \003(\01322.org.jetbrains.kotlin.metadat" +
"a.Annotation.Argument\032\257\005\n\010Argument\022\025\n\007na" +
"me_id\030\001 \002(\005B\004\210\265\030\001\022G\n\005value\030\002 \002(\01328.org.j" +
"etbrains.kotlin.metadata.Annotation.Argu" +
"ment.Value\032\302\004\n\005Value\022K\n\004type\030\001 \001(\0162=.org" +
"tadata/src/ext_options.debug.proto\"\035\n\013St" +
"ringTable\022\016\n\006string\030\001 \003(\t\"\276\002\n\022QualifiedN" +
"ameTable\022W\n\016qualified_name\030\001 \003(\0132?.org.j" +
"etbrains.kotlin.metadata.QualifiedNameTa" +
"ble.QualifiedName\032\316\001\n\rQualifiedName\022!\n\025p" +
"arent_qualified_name\030\001 \001(\005:\002-1\022\022\n\nshort_" +
"name\030\002 \002(\005\022[\n\004kind\030\003 \001(\0162D.org.jetbrains" +
".kotlin.metadata.QualifiedNameTable.Qual",
"ifiedName.Kind:\007PACKAGE\")\n\004Kind\022\t\n\005CLASS" +
"\020\000\022\013\n\007PACKAGE\020\001\022\t\n\005LOCAL\020\002\"\226\006\n\nAnnotatio" +
"n\022\020\n\002id\030\001 \002(\005B\004\220\265\030\001\022D\n\010argument\030\002 \003(\01322." +
"org.jetbrains.kotlin.metadata.Annotation" +
".Argument\032\257\005\n\010Argument\022\025\n\007name_id\030\001 \002(\005B" +
"\004\210\265\030\001\022G\n\005value\030\002 \002(\01328.org.jetbrains.kot" +
"lin.metadata.Annotation.Argument.Value\032\302" +
"\004\n\005Value\022K\n\004type\030\001 \001(\0162=.org.jetbrains.k" +
"otlin.metadata.Annotation.Argument.Value" +
".Type\022\021\n\tint_value\030\002 \001(\022\022\023\n\013float_value\030",
"\003 \001(\002\022\024\n\014double_value\030\004 \001(\001\022\032\n\014string_va" +
"lue\030\005 \001(\005B\004\230\265\030\001\022\026\n\010class_id\030\006 \001(\005B\004\220\265\030\001\022" +
"\033\n\renum_value_id\030\007 \001(\005B\004\210\265\030\001\022=\n\nannotati" +
"on\030\010 \001(\0132).org.jetbrains.kotlin.metadata" +
".Annotation\022O\n\rarray_element\030\t \003(\01328.org" +
".jetbrains.kotlin.metadata.Annotation.Ar" +
"gument.Value.Type\022\021\n\tint_value\030\002 \001(\022\022\023\n\013",
"float_value\030\003 \001(\002\022\024\n\014double_value\030\004 \001(\001\022" +
"\032\n\014string_value\030\005 \001(\005B\004\230\265\030\001\022\026\n\010class_id\030" +
"\006 \001(\005B\004\220\265\030\001\022\033\n\renum_value_id\030\007 \001(\005B\004\210\265\030\001" +
"\022=\n\nannotation\030\010 \001(\0132).org.jetbrains.kot" +
"lin.metadata.Annotation\022O\n\rarray_element" +
"\030\t \003(\01328.org.jetbrains.kotlin.metadata.A" +
"nnotation.Argument.Value\022 \n\025array_dimens" +
"ion_count\030\013 \001(\005:\0010\022\020\n\005flags\030\n \001(\005:\0010\"\230\001\n" +
"\004Type\022\010\n\004BYTE\020\000\022\010\n\004CHAR\020\001\022\t\n\005SHORT\020\002\022\007\n\003" +
"INT\020\003\022\010\n\004LONG\020\004\022\t\n\005FLOAT\020\005\022\n\n\006DOUBLE\020\006\022\013",
"\n\007BOOLEAN\020\007\022\n\n\006STRING\020\010\022\t\n\005CLASS\020\t\022\010\n\004EN" +
"UM\020\n\022\016\n\nANNOTATION\020\013\022\t\n\005ARRAY\020\014\"\223\006\n\004Type" +
"\022>\n\010argument\030\002 \003(\0132,.org.jetbrains.kotli" +
"n.metadata.Type.Argument\022\027\n\010nullable\030\003 \001" +
"(\010:\005false\022+\n\035flexible_type_capabilities_" +
"id\030\004 \001(\005B\004\230\265\030\001\022A\n\024flexible_upper_bound\030\005" +
"gument.Value\022 \n\025array_dimension_count\030\013 " +
"\001(\005:\0010\022\020\n\005flags\030\n \001(\005:\0010\"\230\001\n\004Type\022\010\n\004BYT" +
"E\020\000\022\010\n\004CHAR\020\001\022\t\n\005SHORT\020\002\022\007\n\003INT\020\003\022\010\n\004LON" +
"G\020\004\022\t\n\005FLOAT\020\005\022\n\n\006DOUBLE\020\006\022\013\n\007BOOLEAN\020\007\022",
"\n\n\006STRING\020\010\022\t\n\005CLASS\020\t\022\010\n\004ENUM\020\n\022\016\n\nANNO" +
"TATION\020\013\022\t\n\005ARRAY\020\014\"\373\005\n\004Type\022>\n\010argument" +
"\030\002 \003(\0132,.org.jetbrains.kotlin.metadata.T" +
"ype.Argument\022\027\n\010nullable\030\003 \001(\010:\005false\022+\n" +
"\035flexible_type_capabilities_id\030\004 \001(\005B\004\230\265" +
"\030\001\022A\n\024flexible_upper_bound\030\005 \001(\0132#.org.j" +
"etbrains.kotlin.metadata.Type\022\037\n\027flexibl" +
"e_upper_bound_id\030\010 \001(\005\022\030\n\nclass_name\030\006 \001" +
"(\005B\004\220\265\030\001\022\026\n\016type_parameter\030\007 \001(\005\022!\n\023type" +
"_parameter_name\030\t \001(\005B\004\210\265\030\001\022\035\n\017type_alia",
"s_name\030\014 \001(\005B\004\220\265\030\001\0227\n\nouter_type\030\n \001(\0132#" +
".org.jetbrains.kotlin.metadata.Type\022\025\n\ro" +
"uter_type_id\030\013 \001(\005\022=\n\020abbreviated_type\030\r" +
" \001(\0132#.org.jetbrains.kotlin.metadata.Typ" +
"e\022%\n\027flexible_upper_bound_id\030\010 \001(\005B\004\240\265\030\001" +
"\022\030\n\nclass_name\030\006 \001(\005B\004\220\265\030\001\022\026\n\016type_param" +
"eter\030\007 \001(\005\022!\n\023type_parameter_name\030\t \001(\005B",
"\004\210\265\030\001\022\035\n\017type_alias_name\030\014 \001(\005B\004\220\265\030\001\0227\n\n" +
"outer_type\030\n \001(\0132#.org.jetbrains.kotlin." +
"metadata.Type\022\033\n\router_type_id\030\013 \001(\005B\004\240\265" +
"\030\001\022=\n\020abbreviated_type\030\r \001(\0132#.org.jetbr" +
"ains.kotlin.metadata.Type\022!\n\023abbreviated" +
"_type_id\030\016 \001(\005B\004\240\265\030\001\022\r\n\005flags\030\001 \001(\005\032\330\001\n\010" +
"Argument\022P\n\nprojection\030\001 \001(\01627.org.jetbr" +
"ains.kotlin.metadata.Type.Argument.Proje" +
"ction:\003INV\0221\n\004type\030\002 \001(\0132#.org.jetbrains" +
".kotlin.metadata.Type\022\025\n\007type_id\030\003 \001(\005B\004",
"\240\265\030\001\"0\n\nProjection\022\006\n\002IN\020\000\022\007\n\003OUT\020\001\022\007\n\003I" +
"NV\020\002\022\010\n\004STAR\020\003*\005\010d\020\310\001\"\234\002\n\rTypeParameter\022" +
"\n\n\002id\030\001 \002(\005\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\022\026\n\007reifi" +
"ed\030\003 \001(\010:\005false\022L\n\010variance\030\004 \001(\01625.org." +
"jetbrains.kotlin.metadata.TypeParameter." +
"Variance:\003INV\0228\n\013upper_bound\030\005 \003(\0132#.org" +
".jetbrains.kotlin.metadata.Type\022\036\n\016upper" +
"_bound_id\030\006 \003(\005B\006\020\001\240\265\030\001\"$\n\010Variance\022\006\n\002I" +
"N\020\000\022\007\n\003OUT\020\001\022\007\n\003INV\020\002*\005\010d\020\350\007\"\250\007\n\005Class\022\020" +
"\n\005flags\030\001 \001(\005:\0016\022\025\n\007fq_name\030\003 \002(\005B\004\220\265\030\001\022",
"#\n\025companion_object_name\030\004 \001(\005B\004\210\265\030\001\022D\n\016" +
"e\022\033\n\023abbreviated_type_id\030\016 \001(\005\022\r\n\005flags\030" +
"\001 \001(\005\032\322\001\n\010Argument\022P\n\nprojection\030\001 \001(\01627" +
".org.jetbrains.kotlin.metadata.Type.Argu" +
"ment.Projection:\003INV\0221\n\004type\030\002 \001(\0132#.org" +
".jetbrains.kotlin.metadata.Type\022\017\n\007type_" +
"id\030\003 \001(\005\"0\n\nProjection\022\006\n\002IN\020\000\022\007\n\003OUT\020\001\022",
"\007\n\003INV\020\002\022\010\n\004STAR\020\003*\005\010d\020\310\001\"\230\002\n\rTypeParame" +
"ter\022\n\n\002id\030\001 \002(\005\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\022\026\n\007r" +
"eified\030\003 \001(\010:\005false\022L\n\010variance\030\004 \001(\01625." +
"org.jetbrains.kotlin.metadata.TypeParame" +
"ter.Variance:\003INV\0228\n\013upper_bound\030\005 \003(\0132#" +
".org.jetbrains.kotlin.metadata.Type\022\032\n\016u" +
"pper_bound_id\030\006 \003(\005B\002\020\001\"$\n\010Variance\022\006\n\002I" +
"N\020\000\022\007\n\003OUT\020\001\022\007\n\003INV\020\002*\005\010d\020\350\007\"\244\007\n\005Class\022\020" +
"\n\005flags\030\001 \001(\005:\0016\022\025\n\007fq_name\030\003 \002(\005B\004\220\265\030\001\022" +
"#\n\025companion_object_name\030\004 \001(\005B\004\210\265\030\001\022D\n\016",
"type_parameter\030\005 \003(\0132,.org.jetbrains.kot" +
"lin.metadata.TypeParameter\0226\n\tsupertype\030" +
"\006 \003(\0132#.org.jetbrains.kotlin.metadata.Ty" +
"pe\022\034\n\014supertype_id\030\002 \003(\005B\006\020\001\240\265\030\001\022!\n\021nest" +
"ed_class_name\030\007 \003(\005B\006\020\001\210\265\030\001\022?\n\013construct" +
"or\030\010 \003(\0132*.org.jetbrains.kotlin.metadata" +
".Constructor\0229\n\010function\030\t \003(\0132\'.org.jet" +
"brains.kotlin.metadata.Function\0229\n\010prope" +
"rty\030\n \003(\0132\'.org.jetbrains.kotlin.metadat",
"a.Property\022<\n\ntype_alias\030\013 \003(\0132(.org.jet" +
"brains.kotlin.metadata.TypeAlias\022<\n\nenum" +
"_entry\030\r \003(\0132(.org.jetbrains.kotlin.meta" +
"data.EnumEntry\022\'\n\027sealed_subclass_fq_nam" +
"e\030\020 \003(\005B\006\020\001\220\265\030\001\022<\n\ntype_table\030\036 \001(\0132(.or" +
"g.jetbrains.kotlin.metadata.TypeTable\022\033\n" +
"\023version_requirement\030\037 \003(\005\022Y\n\031version_re" +
"quirement_table\030 \001(\01326.org.jetbrains.ko" +
"tlin.metadata.VersionRequirementTable\"x\n" +
"\004Kind\022\t\n\005CLASS\020\000\022\r\n\tINTERFACE\020\001\022\016\n\nENUM_",
"CLASS\020\002\022\016\n\nENUM_ENTRY\020\003\022\024\n\020ANNOTATION_CL" +
"ASS\020\004\022\n\n\006OBJECT\020\005\022\024\n\020COMPANION_OBJECT\020\006*" +
"\006\010d\020\270\224\001\"\335\002\n\007Package\0229\n\010function\030\003 \003(\0132\'." +
"org.jetbrains.kotlin.metadata.Function\0229" +
"\n\010property\030\004 \003(\0132\'.org.jetbrains.kotlin." +
"metadata.Property\022<\n\ntype_alias\030\005 \003(\0132(." +
"org.jetbrains.kotlin.metadata.TypeAlias\022" +
"<\n\ntype_table\030\036 \001(\0132(.org.jetbrains.kotl" +
"in.metadata.TypeTable\022Y\n\031version_require" +
"ment_table\030 \001(\01326.org.jetbrains.kotlin.",
"metadata.VersionRequirementTable*\005\010d\020\310\001\"" +
"`\n\tTypeTable\0221\n\004type\030\001 \003(\0132#.org.jetbrai" +
"ns.kotlin.metadata.Type\022\032\n\016first_nullabl" +
"e\030\002 \001(\005:\002-1:\004\240\273\030\001\"\214\001\n\013Constructor\022\020\n\005fla" +
"gs\030\001 \001(\005:\0016\022F\n\017value_parameter\030\002 \003(\0132-.o" +
"rg.jetbrains.kotlin.metadata.ValueParame" +
"ter\022\033\n\023version_requirement\030\037 \003(\005*\006\010d\020\270\224\001" +
"\"\246\004\n\010Function\022\020\n\005flags\030\t \001(\005:\0016\022\024\n\told_f" +
"lags\030\001 \001(\005:\0016\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\0228\n\013ret" +
"urn_type\030\003 \001(\0132#.org.jetbrains.kotlin.me",
"tadata.Type\022\034\n\016return_type_id\030\007 \001(\005B\004\240\265\030" +
"\001\022D\n\016type_parameter\030\004 \003(\0132,.org.jetbrain" +
"s.kotlin.metadata.TypeParameter\022:\n\rrecei" +
"ver_type\030\005 \001(\0132#.org.jetbrains.kotlin.me" +
"tadata.Type\022\036\n\020receiver_type_id\030\010 \001(\005B\004\240" +
"\265\030\001\022F\n\017value_parameter\030\006 \003(\0132-.org.jetbr" +
"ains.kotlin.metadata.ValueParameter\022<\n\nt" +
"pe\022\030\n\014supertype_id\030\002 \003(\005B\002\020\001\022!\n\021nested_c" +
"lass_name\030\007 \003(\005B\006\020\001\210\265\030\001\022?\n\013constructor\030\010" +
" \003(\0132*.org.jetbrains.kotlin.metadata.Con" +
"structor\0229\n\010function\030\t \003(\0132\'.org.jetbrai" +
"ns.kotlin.metadata.Function\0229\n\010property\030" +
"\n \003(\0132\'.org.jetbrains.kotlin.metadata.Pr" +
"operty\022<\n\ntype_alias\030\013 \003(\0132(.org.jetbrai",
"ns.kotlin.metadata.TypeAlias\022<\n\nenum_ent" +
"ry\030\r \003(\0132(.org.jetbrains.kotlin.metadata" +
".EnumEntry\022\'\n\027sealed_subclass_fq_name\030\020 " +
"\003(\005B\006\020\001\220\265\030\001\022<\n\ntype_table\030\036 \001(\0132(.org.je" +
"tbrains.kotlin.metadata.TypeTable\022\033\n\023ver" +
"sion_requirement\030\037 \003(\005\022Y\n\031version_requir" +
"ement_table\030 \001(\01326.org.jetbrains.kotlin" +
".metadata.VersionRequirementTable\"x\n\004Kin" +
"d\022\t\n\005CLASS\020\000\022\r\n\tINTERFACE\020\001\022\016\n\nENUM_CLAS" +
"S\020\002\022\016\n\nENUM_ENTRY\020\003\022\024\n\020ANNOTATION_CLASS\020",
"\004\022\n\n\006OBJECT\020\005\022\024\n\020COMPANION_OBJECT\020\006*\006\010d\020" +
"\270\224\001\"\335\002\n\007Package\0229\n\010function\030\003 \003(\0132\'.org." +
"jetbrains.kotlin.metadata.Function\0229\n\010pr" +
"operty\030\004 \003(\0132\'.org.jetbrains.kotlin.meta" +
"data.Property\022<\n\ntype_alias\030\005 \003(\0132(.org." +
"jetbrains.kotlin.metadata.TypeAlias\022<\n\nt" +
"ype_table\030\036 \001(\0132(.org.jetbrains.kotlin.m" +
"etadata.TypeTable\022\033\n\023version_requirement" +
"\030\037 \003(\005\0229\n\010contract\030 \001(\0132\'.org.jetbrains",
".kotlin.metadata.Contract*\006\010d\020\270\224\001\"\345\003\n\010Pr" +
"operty\022\022\n\005flags\030\013 \001(\005:\003518\022\027\n\told_flags\030" +
"\001 \001(\005:\0042054\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\0228\n\013retur" +
"n_type\030\003 \001(\0132#.org.jetbrains.kotlin.meta" +
"data.Type\022\034\n\016return_type_id\030\t \001(\005B\004\240\265\030\001\022" +
"D\n\016type_parameter\030\004 \003(\0132,.org.jetbrains." +
"kotlin.metadata.TypeParameter\022:\n\rreceive" +
"r_type\030\005 \001(\0132#.org.jetbrains.kotlin.meta" +
"data.Type\022\036\n\020receiver_type_id\030\n \001(\005B\004\240\265\030" +
"\001\022M\n\026setter_value_parameter\030\006 \001(\0132-.org.",
"jetbrains.kotlin.metadata.ValueParameter" +
"\022\024\n\014getter_flags\030\007 \001(\005\022\024\n\014setter_flags\030\010" +
" \001(\005\022\033\n\023version_requirement\030\037 \003(\005*\006\010d\020\270\224" +
"\001\"\357\001\n\016ValueParameter\022\020\n\005flags\030\001 \001(\005:\0010\022\022" +
"\n\004name\030\002 \002(\005B\004\210\265\030\001\0221\n\004type\030\003 \001(\0132#.org.j" +
"etbrains.kotlin.metadata.Type\022\025\n\007type_id" +
"\030\005 \001(\005B\004\240\265\030\001\022@\n\023vararg_element_type\030\004 \001(" +
"\0132#.org.jetbrains.kotlin.metadata.Type\022$" +
"\n\026vararg_element_type_id\030\006 \001(\005B\004\240\265\030\001*\005\010d" +
"\020\310\001\"\226\003\n\tTypeAlias\022\020\n\005flags\030\001 \001(\005:\0016\022\022\n\004n",
"ame\030\002 \002(\005B\004\210\265\030\001\022D\n\016type_parameter\030\003 \003(\0132" +
",.org.jetbrains.kotlin.metadata.TypePara" +
"meter\022<\n\017underlying_type\030\004 \001(\0132#.org.jet" +
"brains.kotlin.metadata.Type\022 \n\022underlyin" +
"g_type_id\030\005 \001(\005B\004\240\265\030\001\022:\n\rexpanded_type\030\006" +
"etadata.TypeTable\022Y\n\031version_requirement" +
"_table\030 \001(\01326.org.jetbrains.kotlin.meta" +
"data.VersionRequirementTable*\005\010d\020\310\001\"Z\n\tT",
"ypeTable\0221\n\004type\030\001 \003(\0132#.org.jetbrains.k" +
"otlin.metadata.Type\022\032\n\016first_nullable\030\002 " +
"\001(\005:\002-1\"\214\001\n\013Constructor\022\020\n\005flags\030\001 \001(\005:\001" +
"6\022F\n\017value_parameter\030\002 \003(\0132-.org.jetbrai" +
"ns.kotlin.metadata.ValueParameter\022\033\n\023ver" +
"sion_requirement\030\037 \003(\005*\006\010d\020\270\224\001\"\232\004\n\010Funct" +
"ion\022\020\n\005flags\030\t \001(\005:\0016\022\024\n\told_flags\030\001 \001(\005" +
":\0016\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\0228\n\013return_type\030\003" +
" \001(\0132#.org.jetbrains.kotlin.metadata.Typ" +
"e\022\036\n\020expanded_type_id\030\007 \001(\005B\004\240\265\030\001\022=\n\nann" +
"otation\030\010 \003(\0132).org.jetbrains.kotlin.met" +
"adata.Annotation\022\033\n\023version_requirement\030" +
"\037 \003(\005*\005\010d\020\310\001\"&\n\tEnumEntry\022\022\n\004name\030\001 \001(\005B",
"\004\210\265\030\001*\005\010d\020\310\001\"\225\003\n\022VersionRequirement\022\017\n\007v" +
"ersion\030\001 \001(\005\022\024\n\014version_full\030\002 \001(\005\022M\n\005le" +
"vel\030\003 \001(\01627.org.jetbrains.kotlin.metadat" +
"a.VersionRequirement.Level:\005ERROR\022\022\n\nerr" +
"or_code\030\004 \001(\005\022\025\n\007message\030\005 \001(\005B\004\230\265\030\001\022e\n\014" +
"version_kind\030\006 \001(\0162=.org.jetbrains.kotli" +
"n.metadata.VersionRequirement.VersionKin" +
"d:\020LANGUAGE_VERSION\"+\n\005Level\022\013\n\007WARNING\020" +
"\000\022\t\n\005ERROR\020\001\022\n\n\006HIDDEN\020\002\"J\n\013VersionKind\022" +
"\024\n\020LANGUAGE_VERSION\020\000\022\024\n\020COMPILER_VERSIO",
"N\020\001\022\017\n\013API_VERSION\020\002\"a\n\027VersionRequireme" +
"ntTable\022F\n\013requirement\030\001 \003(\01321.org.jetbr" +
"ains.kotlin.metadata.VersionRequirement\"" +
"\217\002\n\017PackageFragment\022;\n\007strings\030\001 \001(\0132*.o" +
"rg.jetbrains.kotlin.metadata.StringTable" +
"\022J\n\017qualified_names\030\002 \001(\01321.org.jetbrain" +
"s.kotlin.metadata.QualifiedNameTable\0227\n\007" +
"package\030\003 \001(\0132&.org.jetbrains.kotlin.met" +
"adata.Package\0223\n\005class\030\004 \003(\0132$.org.jetbr" +
"ains.kotlin.metadata.Class*\005\010d\020\310\001\"A\n\010Con",
"tract\0225\n\006effect\030\001 \003(\0132%.org.jetbrains.ko" +
"tlin.metadata.Effect\"\306\003\n\006Effect\022E\n\013effec" +
"t_type\030\001 \001(\01620.org.jetbrains.kotlin.meta" +
"data.Effect.EffectType\022N\n\033effect_constru" +
"ctor_argument\030\002 \003(\0132).org.jetbrains.kotl" +
"in.metadata.Expression\022S\n conclusion_of_" +
"conditional_effect\030\003 \001(\0132).org.jetbrains" +
".kotlin.metadata.Expression\022B\n\004kind\030\004 \001(" +
"\01624.org.jetbrains.kotlin.metadata.Effect" +
".InvocationKind\"C\n\nEffectType\022\024\n\020RETURNS",
"_CONSTANT\020\000\022\t\n\005CALLS\020\001\022\024\n\020RETURNS_NOT_NU" +
"LL\020\002\"G\n\016InvocationKind\022\020\n\014AT_MOST_ONCE\020\000" +
"\022\020\n\014EXACTLY_ONCE\020\001\022\021\n\rAT_LEAST_ONCE\020\002\"\245\003" +
"\n\nExpression\022\020\n\005flags\030\001 \001(\005:\0010\022!\n\031value_" +
"parameter_reference\030\002 \001(\005\022O\n\016constant_va" +
"lue\030\003 \001(\01627.org.jetbrains.kotlin.metadat" +
"a.Expression.ConstantValue\022=\n\020is_instanc" +
"e_type\030\004 \001(\0132#.org.jetbrains.kotlin.meta" +
"data.Type\022!\n\023is_instance_type_id\030\005 \001(\005B\004" +
"\240\265\030\001\022?\n\014and_argument\030\006 \003(\0132).org.jetbrai",
"ns.kotlin.metadata.Expression\022>\n\013or_argu" +
"ment\030\007 \003(\0132).org.jetbrains.kotlin.metada" +
"ta.Expression\".\n\rConstantValue\022\010\n\004TRUE\020\000" +
"\022\t\n\005FALSE\020\001\022\010\n\004NULL\020\002*9\n\010Modality\022\t\n\005FIN" +
"AL\020\000\022\010\n\004OPEN\020\001\022\014\n\010ABSTRACT\020\002\022\n\n\006SEALED\020\003" +
"*b\n\nVisibility\022\014\n\010INTERNAL\020\000\022\013\n\007PRIVATE\020" +
"\001\022\r\n\tPROTECTED\020\002\022\n\n\006PUBLIC\020\003\022\023\n\017PRIVATE_" +
"TO_THIS\020\004\022\t\n\005LOCAL\020\005*Q\n\nMemberKind\022\017\n\013DE" +
"CLARATION\020\000\022\021\n\rFAKE_OVERRIDE\020\001\022\016\n\nDELEGA" +
"TION\020\002\022\017\n\013SYNTHESIZED\020\003B\017B\rDebugProtoBuf"
"e\022\026\n\016return_type_id\030\007 \001(\005\022D\n\016type_parame",
"ter\030\004 \003(\0132,.org.jetbrains.kotlin.metadat" +
"a.TypeParameter\022:\n\rreceiver_type\030\005 \001(\0132#" +
".org.jetbrains.kotlin.metadata.Type\022\030\n\020r" +
"eceiver_type_id\030\010 \001(\005\022F\n\017value_parameter" +
"\030\006 \003(\0132-.org.jetbrains.kotlin.metadata.V" +
"alueParameter\022<\n\ntype_table\030\036 \001(\0132(.org." +
"jetbrains.kotlin.metadata.TypeTable\022\033\n\023v" +
"ersion_requirement\030\037 \003(\005\0229\n\010contract\030 \001" +
"(\0132\'.org.jetbrains.kotlin.metadata.Contr" +
"act*\006\010d\020\270\224\001\"\331\003\n\010Property\022\022\n\005flags\030\013 \001(\005:",
"\003518\022\027\n\told_flags\030\001 \001(\005:\0042054\022\022\n\004name\030\002 " +
"\002(\005B\004\210\265\030\001\0228\n\013return_type\030\003 \001(\0132#.org.jet" +
"brains.kotlin.metadata.Type\022\026\n\016return_ty" +
"pe_id\030\t \001(\005\022D\n\016type_parameter\030\004 \003(\0132,.or" +
"g.jetbrains.kotlin.metadata.TypeParamete" +
"r\022:\n\rreceiver_type\030\005 \001(\0132#.org.jetbrains" +
".kotlin.metadata.Type\022\030\n\020receiver_type_i" +
"d\030\n \001(\005\022M\n\026setter_value_parameter\030\006 \001(\0132" +
"-.org.jetbrains.kotlin.metadata.ValuePar" +
"ameter\022\024\n\014getter_flags\030\007 \001(\005\022\024\n\014setter_f",
"lags\030\010 \001(\005\022\033\n\023version_requirement\030\037 \003(\005*" +
"\006\010d\020\270\224\001\"\343\001\n\016ValueParameter\022\020\n\005flags\030\001 \001(" +
"\005:\0010\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\0221\n\004type\030\003 \001(\0132#" +
".org.jetbrains.kotlin.metadata.Type\022\017\n\007t" +
"ype_id\030\005 \001(\005\022@\n\023vararg_element_type\030\004 \001(" +
"\0132#.org.jetbrains.kotlin.metadata.Type\022\036" +
"\n\026vararg_element_type_id\030\006 \001(\005*\005\010d\020\310\001\"\212\003" +
"\n\tTypeAlias\022\020\n\005flags\030\001 \001(\005:\0016\022\022\n\004name\030\002 " +
"\002(\005B\004\210\265\030\001\022D\n\016type_parameter\030\003 \003(\0132,.org." +
"jetbrains.kotlin.metadata.TypeParameter\022",
"<\n\017underlying_type\030\004 \001(\0132#.org.jetbrains" +
".kotlin.metadata.Type\022\032\n\022underlying_type" +
"_id\030\005 \001(\005\022:\n\rexpanded_type\030\006 \001(\0132#.org.j" +
"etbrains.kotlin.metadata.Type\022\030\n\020expande" +
"d_type_id\030\007 \001(\005\022=\n\nannotation\030\010 \003(\0132).or" +
"g.jetbrains.kotlin.metadata.Annotation\022\033" +
"\n\023version_requirement\030\037 \003(\005*\005\010d\020\310\001\"&\n\tEn" +
"umEntry\022\022\n\004name\030\001 \001(\005B\004\210\265\030\001*\005\010d\020\310\001\"\225\003\n\022V" +
"ersionRequirement\022\017\n\007version\030\001 \001(\005\022\024\n\014ve" +
"rsion_full\030\002 \001(\005\022M\n\005level\030\003 \001(\01627.org.je",
"tbrains.kotlin.metadata.VersionRequireme" +
"nt.Level:\005ERROR\022\022\n\nerror_code\030\004 \001(\005\022\025\n\007m" +
"essage\030\005 \001(\005B\004\230\265\030\001\022e\n\014version_kind\030\006 \001(\016" +
"2=.org.jetbrains.kotlin.metadata.Version" +
"Requirement.VersionKind:\020LANGUAGE_VERSIO" +
"N\"+\n\005Level\022\013\n\007WARNING\020\000\022\t\n\005ERROR\020\001\022\n\n\006HI" +
"DDEN\020\002\"J\n\013VersionKind\022\024\n\020LANGUAGE_VERSIO" +
"N\020\000\022\024\n\020COMPILER_VERSION\020\001\022\017\n\013API_VERSION" +
"\020\002\"a\n\027VersionRequirementTable\022F\n\013require" +
"ment\030\001 \003(\01321.org.jetbrains.kotlin.metada",
"ta.VersionRequirement\"\217\002\n\017PackageFragmen" +
"t\022;\n\007strings\030\001 \001(\0132*.org.jetbrains.kotli" +
"n.metadata.StringTable\022J\n\017qualified_name" +
"s\030\002 \001(\01321.org.jetbrains.kotlin.metadata." +
"QualifiedNameTable\0227\n\007package\030\003 \001(\0132&.or" +
"g.jetbrains.kotlin.metadata.Package\0223\n\005c" +
"lass\030\004 \003(\0132$.org.jetbrains.kotlin.metada" +
"ta.Class*\005\010d\020\310\001\"A\n\010Contract\0225\n\006effect\030\001 " +
"\003(\0132%.org.jetbrains.kotlin.metadata.Effe" +
"ct\"\306\003\n\006Effect\022E\n\013effect_type\030\001 \001(\01620.org",
".jetbrains.kotlin.metadata.Effect.Effect" +
"Type\022N\n\033effect_constructor_argument\030\002 \003(" +
"\0132).org.jetbrains.kotlin.metadata.Expres" +
"sion\022S\n conclusion_of_conditional_effect" +
"\030\003 \001(\0132).org.jetbrains.kotlin.metadata.E" +
"xpression\022B\n\004kind\030\004 \001(\01624.org.jetbrains." +
"kotlin.metadata.Effect.InvocationKind\"C\n" +
"\nEffectType\022\024\n\020RETURNS_CONSTANT\020\000\022\t\n\005CAL" +
"LS\020\001\022\024\n\020RETURNS_NOT_NULL\020\002\"G\n\016Invocation" +
"Kind\022\020\n\014AT_MOST_ONCE\020\000\022\020\n\014EXACTLY_ONCE\020\001",
"\022\021\n\rAT_LEAST_ONCE\020\002\"\237\003\n\nExpression\022\020\n\005fl" +
"ags\030\001 \001(\005:\0010\022!\n\031value_parameter_referenc" +
"e\030\002 \001(\005\022O\n\016constant_value\030\003 \001(\01627.org.je" +
"tbrains.kotlin.metadata.Expression.Const" +
"antValue\022=\n\020is_instance_type\030\004 \001(\0132#.org" +
".jetbrains.kotlin.metadata.Type\022\033\n\023is_in" +
"stance_type_id\030\005 \001(\005\022?\n\014and_argument\030\006 \003" +
"(\0132).org.jetbrains.kotlin.metadata.Expre" +
"ssion\022>\n\013or_argument\030\007 \003(\0132).org.jetbrai" +
"ns.kotlin.metadata.Expression\".\n\rConstan",
"tValue\022\010\n\004TRUE\020\000\022\t\n\005FALSE\020\001\022\010\n\004NULL\020\002*9\n" +
"\010Modality\022\t\n\005FINAL\020\000\022\010\n\004OPEN\020\001\022\014\n\010ABSTRA" +
"CT\020\002\022\n\n\006SEALED\020\003*b\n\nVisibility\022\014\n\010INTERN" +
"AL\020\000\022\013\n\007PRIVATE\020\001\022\r\n\tPROTECTED\020\002\022\n\n\006PUBL" +
"IC\020\003\022\023\n\017PRIVATE_TO_THIS\020\004\022\t\n\005LOCAL\020\005*Q\n\n" +
"MemberKind\022\017\n\013DECLARATION\020\000\022\021\n\rFAKE_OVER" +
"RIDE\020\001\022\016\n\nDELEGATION\020\002\022\017\n\013SYNTHESIZED\020\003B" +
"\017B\rDebugProtoBuf"
};
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
@@ -34658,44 +34648,26 @@ public final class DebugProtoBuf {
new java.lang.String[] { "Flags", "ValueParameterReference", "ConstantValue", "IsInstanceType", "IsInstanceTypeId", "AndArgument", "OrArgument", });
org.jetbrains.kotlin.protobuf.ExtensionRegistry registry =
org.jetbrains.kotlin.protobuf.ExtensionRegistry.newInstance();
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.skipMessageInComparison);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.skipMessageInComparison);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.stringIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.stringIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.skipMessageInComparison);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.fqNameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.nameIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.stringIdInTable);
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.typeIdInTable);
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor
.internalUpdateFileDescriptor(descriptor, registry);
org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.getDescriptor();

View File

@@ -1,17 +1,20 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import proguard.gradle.ProGuardTask
import org.gradle.kotlin.dsl.*
buildscript {
extra["defaultSnapshotVersion"] = "1.3-SNAPSHOT"
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
kotlinBootstrapFrom(BootstrapOption.BintrayBootstrap(kotlinBuildProperties.kotlinBootstrapVersion!!, cacheRedirectorEnabled))
// when updating please also update JPS artifacts configuration: https://jetbrains.quip.com/zzGUAYSJ6gv3/JPS-Build-update-bootstrap
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.3.50-dev-526", onlySuccessBootstrap = false))
repositories {
bootstrapKotlinRepo?.let(::maven)
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
if (cacheRedirectorEnabled) {
maven("https://cache-redirector.jetbrains.com/plugins.gradle.org/m2")
} else {
@@ -27,18 +30,15 @@ buildscript {
dependencies {
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
classpath("com.gradle.publish:plugin-publish-plugin:0.9.7")
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
classpath("net.sf.proguard:proguard-gradle:6.1.0")
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
}
}
if (kotlinBuildProperties.buildScanServer != null) {
apply(from = "gradle/buildScanUserData.gradle")
}
plugins {
`build-scan`
idea
id("jps-compatible")
id("org.jetbrains.gradle.plugin.idea-ext")
@@ -53,10 +53,10 @@ pill {
)
}
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
val includeStdlibJsIr by extra(
findProperty("include.stdlib.js.ir")?.let { it.toString().toBoolean() } ?: isTeamcityBuild
)
buildScan {
setTermsOfServiceUrl("https://gradle.com/terms-of-service")
setTermsOfServiceAgree("yes")
}
val configuredJdks: List<JdkId> =
getConfiguredJdks().also {
@@ -69,7 +69,7 @@ val defaultSnapshotVersion: String by extra
val buildNumber by extra(findProperty("build.number")?.toString() ?: defaultSnapshotVersion)
val kotlinVersion by extra(findProperty("deployVersion")?.toString() ?: buildNumber)
val kotlinLanguageVersion by extra("1.4")
val kotlinLanguageVersion by extra("1.3")
allprojects {
group = "org.jetbrains.kotlin"
@@ -115,31 +115,37 @@ extra["isSonatypeRelease"] = false
// Work-around necessary to avoid setting null javaHome. Will be removed after support of lazy task configuration
val jdkNotFoundConst = "JDK NOT FOUND"
if (isTeamcityBuild) {
extra["JDK_16"] = jdkPath("1.6")
extra["JDK_17"] = jdkPath("1.7")
} else {
extra["JDK_16"] = jdkPath("1.6", "1.8")
extra["JDK_17"] = jdkPath("1.7", "1.8")
}
extra["JDK_16"] = jdkPath("1.6")
extra["JDK_17"] = jdkPath("1.7")
extra["JDK_18"] = jdkPath("1.8")
extra["JDK_9"] = jdkPath("9")
extra["JDK_10"] = jdkPath("10")
extra["JDK_11"] = jdkPath("11")
// allow opening the project without setting up all env variables (see KT-26413)
if (!kotlinBuildProperties.isInIdeaSync) {
gradle.taskGraph.beforeTask() {
checkJDK()
}
var jdkChecked: Boolean = false
fun checkJDK() {
val missingEnvVars = JdkMajorVersion.values()
.filter { it.isMandatory() && extra[it.name] == jdkNotFoundConst }
.mapTo(ArrayList()) { it.name }
if (missingEnvVars.isNotEmpty()) {
throw GradleException("Required environment variables are missing: ${missingEnvVars.joinToString()}")
if (jdkChecked) {
return
}
val unpresentJdks = JdkMajorVersion.values()
.filter { it.isMandatory() }
.map { it.name }
.filter { extra[it] == jdkNotFoundConst }
.toList()
if (unpresentJdks.isNotEmpty()) {
throw GradleException("Please set environment variable" +
(if (unpresentJdks.size > 1) "s" else "") +
": " + unpresentJdks.joinToString() +
" to point to corresponding JDK installation.")
}
jdkChecked = true
}
rootProject.apply {
@@ -147,11 +153,9 @@ rootProject.apply {
from(rootProject.file("gradle/report.gradle.kts"))
from(rootProject.file("gradle/javaInstrumentation.gradle.kts"))
from(rootProject.file("gradle/jps.gradle.kts"))
from(rootProject.file("gradle/checkArtifacts.gradle.kts"))
from(rootProject.file("gradle/checkCacheability.gradle.kts"))
}
IdeVersionConfigurator.setCurrentIde(project)
IdeVersionConfigurator.setCurrentIde(this)
extra["versions.protobuf"] = "2.6.1"
extra["versions.javax.inject"] = "1"
@@ -173,17 +177,15 @@ extra["versions.org.springframework"] = "4.2.0.RELEASE"
extra["versions.jflex"] = "1.7.0"
extra["versions.markdown"] = "0.1.25"
extra["versions.trove4j"] = "1.0.20181211"
extra["versions.completion-ranking-kotlin"] = "0.1.2"
extra["versions.r8"] = "1.5.70"
extra["versions.kotlinx-collections-immutable"] = "0.3.1"
// NOTE: please, also change KTOR_NAME in pathUtil.kt and all versions in corresponding jar names in daemon tests.
extra["versions.ktor-network"] = "1.0.1"
if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.4-M2-dev-15123"
extra["versions.kotlin-native"] = "1.3.50-dev-11052"
}
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled)
val effectSystemEnabled by extra(project.getBooleanProperty("kotlin.compiler.effectSystemEnabled") ?: false)
val newInferenceEnabled by extra(project.getBooleanProperty("kotlin.compiler.newInferenceEnabled") ?: false)
@@ -199,17 +201,15 @@ extra["IntellijCoreDependencies"] =
"jdom",
"jna",
"log4j",
if (Platform[201].orHigher()) null else "picocontainer",
"picocontainer",
"snappy-in-java",
"streamex",
"trove4j"
).filterNotNull()
)
extra["compilerModules"] = arrayOf(
":compiler:util",
":compiler:config",
":compiler:config.jvm",
":compiler:container",
":compiler:resolution",
":compiler:serialization",
@@ -223,73 +223,56 @@ extra["compilerModules"] = arrayOf(
":compiler:ir.backend.common",
":compiler:backend.jvm",
":compiler:backend.js",
":compiler:backend.wasm",
":compiler:ir.serialization.common",
":compiler:ir.serialization.js",
":compiler:ir.serialization.jvm",
":kotlin-util-io",
":kotlin-util-klib",
":kotlin-util-klib-metadata",
":compiler:backend-common",
":compiler:backend",
":compiler:plugin-api",
":compiler:light-classes",
":compiler:javac-wrapper",
":compiler:cli",
":compiler:cli-js",
":compiler:incremental-compilation-impl",
":compiler:compiler.version",
":js:js.ast",
":js:js.serializer",
":js:js.parser",
":js:js.config",
":js:js.frontend",
":js:js.translator",
":js:js.dce",
":native:frontend.native",
":native:kotlin-native-utils",
":compiler",
":kotlin-build-common",
":core:metadata",
":core:metadata.jvm",
":core:descriptors",
":core:descriptors.jvm",
":core:descriptors.runtime",
":core:deserialization",
":core:util.runtime",
":core:type-system",
":compiler:fir:cones",
":compiler:fir:resolve",
":compiler:fir:tree",
":compiler:fir:raw-fir:fir-common",
":compiler:fir:raw-fir:psi2fir",
":compiler:fir:raw-fir:light-tree2fir",
":compiler:fir:psi2fir",
":compiler:fir:fir2ir",
":compiler:fir:fir2ir:jvm-backend",
":compiler:fir:java",
":compiler:fir:jvm",
":compiler:fir:checkers",
":compiler:fir:analysis-tests"
":compiler:fir:java"
)
val coreLibProjects = listOfNotNull(
":kotlin-stdlib",
":kotlin-stdlib-common",
":kotlin-stdlib-js",
// Exclude JS IR from core libs because it depends on local compiler build, which
// in turn depends on local JVM stdlib. It slows down library testing.
":kotlin-stdlib-js-ir".takeIf { includeStdlibJsIr },
// Local builds are disabled at the request of the lib team
// TODO: Enable when tests are fixed
":kotlin-stdlib-js-ir".takeIf { isTeamcityBuild },
":kotlin-stdlib-jdk7",
":kotlin-stdlib-jdk8",
":kotlin-test:kotlin-test-annotations-common",
":kotlin-test:kotlin-test-common",
":kotlin-test:kotlin-test-jvm",
":kotlin-test:kotlin-test-junit",
":kotlin-test:kotlin-test-junit5",
":kotlin-test:kotlin-test-testng",
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
":kotlin-reflect",
":kotlin-coroutines-experimental-compat"
":kotlin-test:kotlin-test-js",
":kotlin-reflect"
)
val gradlePluginProjects = listOf(
@@ -352,8 +335,6 @@ allprojects {
maven(intellijRepo)
maven("https://dl.bintray.com/kotlin/ktor")
maven("https://kotlin.bintray.com/kotlin-dependencies")
maven("https://jetbrains.bintray.com/intellij-third-party-dependencies")
maven("https://dl.google.com/dl/android/maven2")
bootstrapKotlinRepo?.let(::maven)
internalKotlinRepo?.let(::maven)
}
@@ -361,11 +342,10 @@ allprojects {
configureJvmProject(javaHome!!, jvmTarget!!)
val commonCompilerArgs = listOfNotNull(
"-Xopt-in=kotlin.RequiresOptIn",
"-Xallow-kotlin-package",
"-Xread-deserialized-contracts",
"-Xjvm-default=compatibility",
"-Xno-optimized-callable-references",
"-progressive".takeIf { hasProperty("test.progressive.mode") }
"-Xprogressive".takeIf { hasProperty("test.progressive.mode") } // TODO: change to "-progressive" after bootstrap
)
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
@@ -394,30 +374,11 @@ allprojects {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
tasks.withType<AbstractArchiveTask> {
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
task("listArchives") { listConfigurationContents("archives") }
tasks.withType<Test> {
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KT-37089") { true }
}
task("listRuntimeJar") { listConfigurationContents("runtimeJar") }
normalization {
runtimeClasspath {
ignore("META-INF/MANIFEST.MF")
ignore("META-INF/compiler.version")
ignore("META-INF/plugin.xml")
}
}
tasks {
register("listArchives") { listConfigurationContents("archives") }
register("listRuntimeJar") { listConfigurationContents("runtimeJar") }
register("listDistJar") { listConfigurationContents("distJar") }
}
task("listDistJar") { listConfigurationContents("distJar") }
afterEvaluate {
if (javaHome != defaultJavaHome || jvmTarget != defaultJvmTarget) {
@@ -435,12 +396,10 @@ allprojects {
} catch (_: UnknownDomainObjectException) {
null
}?.let { javaConvention ->
tasks {
register("printCompileClasspath") { doFirst { javaConvention.sourceSets["main"].compileClasspath.printClassPath("compile") } }
register("printRuntimeClasspath") { doFirst { javaConvention.sourceSets["main"].runtimeClasspath.printClassPath("runtime") } }
register("printTestCompileClasspath") { doFirst { javaConvention.sourceSets["test"].compileClasspath.printClassPath("test compile") } }
register("printTestRuntimeClasspath") { doFirst { javaConvention.sourceSets["test"].runtimeClasspath.printClassPath("test runtime") } }
}
task("printCompileClasspath") { doFirst { javaConvention.sourceSets["main"].compileClasspath.printClassPath("compile") } }
task("printRuntimeClasspath") { doFirst { javaConvention.sourceSets["main"].runtimeClasspath.printClassPath("runtime") } }
task("printTestCompileClasspath") { doFirst { javaConvention.sourceSets["test"].compileClasspath.printClassPath("test compile") } }
task("printTestRuntimeClasspath") { doFirst { javaConvention.sourceSets["test"].runtimeClasspath.printClassPath("test runtime") } }
}
run configureCompilerClasspath@{
@@ -448,9 +407,6 @@ allprojects {
configurations.findByName("kotlinCompilerClasspath")?.let {
dependencies.add(it.name, files(bootstrapCompilerClasspath))
}
configurations.findByName("kotlinCompilerPluginClasspath")
?.exclude("org.jetbrains.kotlin", "kotlin-scripting-compiler-embeddable")
}
// Aggregate task for build related checks
@@ -461,18 +417,23 @@ allprojects {
}
gradle.taskGraph.whenReady {
fun Boolean.toOnOff(): String = if (this) "on" else "off"
val profile = if (isTeamcityBuild) "CI" else "Local"
logger.warn("$profile build profile is active (proguard is ${kotlinBuildProperties.proguard.toOnOff()}" +
", jar compression is ${kotlinBuildProperties.jarCompression.toOnOff()})." +
" Use -Pteamcity=<true|false> to reproduce CI/local build")
allTasks.filterIsInstance<org.gradle.jvm.tasks.Jar>().forEach { task ->
task.entryCompression = if (kotlinBuildProperties.jarCompression)
ZipEntryCompression.DEFLATED
else
ZipEntryCompression.STORED
if (isTeamcityBuild) {
logger.warn("CI build profile is active (IC is off, proguard is on). Use -Pteamcity=false to reproduce local build")
for (task in allTasks) {
when (task) {
is AbstractKotlinCompile<*> -> task.incremental = false
is JavaCompile -> task.options.isIncremental = false
}
}
} else {
logger.warn("Local build profile is active (IC is on, proguard is off). Use -Pteamcity=true to reproduce TC build")
for (task in allTasks) {
when (task) {
// todo: remove when Gradle 4.10+ is used (Java IC on by default)
is JavaCompile -> task.options.isIncremental = true
is org.gradle.jvm.tasks.Jar -> task.entryCompression = ZipEntryCompression.STORED
}
}
}
}
@@ -492,29 +453,29 @@ val ideaPlugin by task<Task> {
}
tasks {
register("clean") {
create("clean") {
doLast {
delete("$buildDir/repo")
delete(distDir)
}
}
register("cleanupArtifacts") {
create("cleanupArtifacts") {
doLast {
delete(artifactsDir)
}
}
listOf("clean", "assemble", "install", "dist").forEach { taskName ->
register("coreLibs${taskName.capitalize()}") {
create("coreLibs${taskName.capitalize()}") {
coreLibProjects.forEach { projectName -> dependsOn("$projectName:$taskName") }
}
}
register("coreLibsTest") {
create("coreLibsTest") {
(coreLibProjects + listOf(
":kotlin-stdlib:samples",
":kotlin-test:kotlin-test-js:kotlin-test-js-it".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
":kotlin-test:kotlin-test-js:kotlin-test-js-it",
":kotlinx-metadata-jvm",
":tools:binary-compatibility-validator"
)).forEach {
@@ -522,140 +483,98 @@ tasks {
}
}
register("gradlePluginTest") {
create("gradlePluginTest") {
gradlePluginProjects.forEach {
dependsOn("$it:check")
}
}
register("gradlePluginIntegrationTest") {
create("gradlePluginIntegrationTest") {
dependsOn(":kotlin-gradle-plugin-integration-tests:check")
}
register("jvmCompilerTest") {
create("jvmCompilerTest") {
dependsOn("dist")
dependsOn(
":compiler:test",
":compiler:container:test",
":compiler:tests-java8:test",
":compiler:tests-spec:test",
":compiler:tests-against-klib:test"
":compiler:tests-spec:remoteRunTests"
)
dependsOn(":plugins:jvm-abi-gen:test")
}
register("jvmCompilerIntegrationTest") {
dependsOn(
":kotlin-compiler-embeddable:test",
":kotlin-compiler-client-embeddable:test"
)
}
register("jsCompilerTest") {
create("jsCompilerTest") {
dependsOn(":js:js.tests:test")
dependsOn(":js:js.tests:runMocha")
}
register("wasmCompilerTest") {
// TODO: fix once
// dependsOn(":js:js.tests:wasmTest")
}
register("nativeCompilerTest") {
dependsOn(":native:kotlin-native-utils:test")
}
register("firCompilerTest") {
dependsOn(":compiler:fir:raw-fir:psi2fir:test")
dependsOn(":compiler:fir:raw-fir:light-tree2fir:test")
dependsOn(":compiler:fir:analysis-tests:test")
create("firCompilerTest") {
dependsOn(":compiler:fir:psi2fir:test")
dependsOn(":compiler:fir:resolve:test")
dependsOn(":compiler:fir:fir2ir:test")
}
register("firAllTest") {
dependsOn(
":compiler:fir:raw-fir:psi2fir:test",
":compiler:fir:raw-fir:light-tree2fir:test",
":compiler:fir:analysis-tests:test",
":compiler:fir:fir2ir:test",
":idea:idea-fir:test"
)
}
register("compilerFrontendVisualizerTest") {
dependsOn("compiler:visualizer:test")
}
register("scriptingTest") {
create("scriptingTest") {
dependsOn("dist")
dependsOn(":kotlin-script-util:test")
dependsOn(":kotlin-scripting-compiler:test")
dependsOn(":kotlin-scripting-common:test")
dependsOn(":kotlin-scripting-jvm:test")
dependsOn(":kotlin-scripting-jvm-host-test:test")
dependsOn(":kotlin-scripting-dependencies:test")
dependsOn(":kotlin-scripting-dependencies-maven:test")
dependsOn(":kotlin-scripting-jsr223-test:test")
// see comments on the task in kotlin-scripting-jvm-host-test
// dependsOn(":kotlin-scripting-jvm-host-test:embeddableTest")
dependsOn(":kotlin-scripting-jvm-host-test:embeddableTest")
dependsOn(":kotlin-scripting-jsr223-test:embeddableTest")
dependsOn(":kotlin-main-kts-test:test")
}
register("compilerTest") {
create("compilerTest") {
dependsOn("jvmCompilerTest")
dependsOn("jsCompilerTest")
dependsOn("wasmCompilerTest")
dependsOn("nativeCompilerTest")
dependsOn("firCompilerTest")
dependsOn("scriptingTest")
dependsOn(":kotlin-build-common:test")
dependsOn(":compiler:incremental-compilation-impl:test")
dependsOn(":core:descriptors.runtime:test")
dependsOn("jvmCompilerIntegrationTest")
}
register("toolsTest") {
create("toolsTest") {
dependsOn(":tools:kotlinp:test")
dependsOn(":native:kotlin-klib-commonizer:test")
}
register("examplesTest") {
create("examplesTest") {
dependsOn("dist")
(project(":examples").subprojects + project(":kotlin-gradle-subplugin-example")).forEach { p ->
dependsOn("${p.path}:check")
}
}
register("distTest") {
create("distTest") {
dependsOn("compilerTest")
dependsOn("toolsTest")
dependsOn("gradlePluginTest")
dependsOn("examplesTest")
}
register("specTest") {
create("specTest") {
dependsOn("dist")
dependsOn(":compiler:tests-spec:test")
}
register("androidCodegenTest") {
create("androidCodegenTest") {
dependsOn(":compiler:android-tests:test")
}
register("jps-tests") {
create("jps-tests") {
dependsOn("dist")
dependsOn(":jps-plugin:test")
}
register("idea-plugin-main-tests") {
create("idea-plugin-main-tests") {
dependsOn("dist")
dependsOn(":idea:test")
}
register("idea-plugin-additional-tests") {
create("idea-plugin-additional-tests") {
dependsOn("dist")
dependsOn(
":idea:idea-gradle:test",
@@ -666,42 +585,19 @@ tasks {
":idea:jvm-debugger:jvm-debugger-core:test",
":idea:jvm-debugger:jvm-debugger-evaluation:test",
":idea:jvm-debugger:jvm-debugger-sequence:test",
":idea:jvm-debugger:eval4j:test",
":idea:scripting-support:test",
":idea:idea-fir:test"
":idea:jvm-debugger:eval4j:test"
)
}
if (Ide.IJ()) {
register("idea-new-project-wizard-tests") {
dependsOn("dist")
dependsOn(
":libraries:tools:new-project-wizard:test",
":libraries:tools:new-project-wizard:new-project-wizard-cli:test",
":idea:idea-new-project-wizard:test"
)
}
}
register("idea-plugin-tests") {
create("idea-plugin-tests") {
dependsOn("dist")
dependsOn(
"idea-plugin-main-tests",
"idea-plugin-additional-tests"
)
if (Ide.IJ()) {
dependsOn("idea-new-project-wizard-tests")
}
}
register("idea-plugin-performance-tests") {
dependsOn("dist")
dependsOn(
":idea:performanceTests:performanceTest"
)
}
register("android-ide-tests") {
create("android-ide-tests") {
dependsOn("dist")
dependsOn(
":plugins:android-extensions-ide:test",
@@ -710,7 +606,7 @@ tasks {
)
}
register("plugins-tests") {
create("plugins-tests") {
dependsOn("dist")
dependsOn(
":kotlin-annotation-processing:test",
@@ -721,13 +617,12 @@ tasks {
":plugins:uast-kotlin:test",
":kotlin-annotation-processing-gradle:test",
":kotlinx-serialization-compiler-plugin:test",
":kotlinx-serialization-ide-plugin:test",
":idea:jvm-debugger:jvm-debugger-test:test"
":kotlinx-serialization-ide-plugin:test"
)
}
register("ideaPluginTest") {
create("ideaPluginTest") {
dependsOn(
"idea-plugin-tests",
"jps-tests",
@@ -738,13 +633,13 @@ tasks {
}
register("test") {
create("test") {
doLast {
throw GradleException("Don't use directly, use aggregate tasks *-check instead")
}
}
register("check") {
create("check") {
dependsOn("test")
}
}
@@ -773,7 +668,6 @@ val zipStdlibTests by task<Zip> {
archiveFileName.set("kotlin-stdlib-tests.zip")
from("libraries/stdlib/common/test") { into("common") }
from("libraries/stdlib/test") { into("test") }
from("libraries/kotlin.test/common/src/test/kotlin") { into("kotlin-test") }
doLast {
logger.lifecycle("Stdlib tests are packed to ${archiveFile.get()}")
}
@@ -824,33 +718,22 @@ configure<IdeaModel> {
commonLocalDataDir,
".gradle",
"dependencies",
"dist",
"tmp"
"dist"
).toSet()
}
}
fun jdkPathOrNull(version: String): String? {
fun jdkPath(version: String): String {
val jdkName = "JDK_${version.replace(".", "")}"
val jdkMajorVersion = JdkMajorVersion.valueOf(jdkName)
return configuredJdks.find { it.majorVersion == jdkMajorVersion }?.homeDir?.canonicalPath
return configuredJdks.find { it.majorVersion == jdkMajorVersion }?.homeDir?.canonicalPath ?: jdkNotFoundConst
}
fun jdkPath(version: String, vararg replacementVersions: String): String {
return jdkPathOrNull(version) ?: run {
replacementVersions.asSequence().map { jdkPathOrNull(it) }.find { it != null }
} ?: jdkNotFoundConst
}
fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
val currentJavaHome = File(System.getProperty("java.home")!!).canonicalPath
val shouldFork = !currentJavaHome.startsWith(File(javaHome).canonicalPath)
tasks.withType<JavaCompile> {
if (name != "compileJava9Java") {
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
options.isFork = shouldFork
options.isFork = true
options.forkOptions.javaHome = file(javaHome)
options.compilerArgs.add("-proc:none")
options.encoding = "UTF-8"
@@ -866,81 +749,42 @@ fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
tasks.withType<Test> {
executable = File(javaHome, "bin/java").canonicalPath
}
plugins.withId("java-base") {
configureShadowJarSubstitutionInCompileClasspath()
}
}
fun Project.configureShadowJarSubstitutionInCompileClasspath() {
val substitutionMap = mapOf(":kotlin-reflect" to ":kotlin-reflect-api")
fun configureSubstitution(substitution: DependencySubstitution) {
val requestedProject = (substitution.requested as? ProjectComponentSelector)?.projectPath ?: return
val replacementProject = substitutionMap[requestedProject] ?: return
substitution.useTarget(project(replacementProject), "Non-default shadow jars should not be used in compile classpath")
tasks.create("findShadowJarsInClasspath").doLast {
fun Collection<File>.printSorted(indent: String = " ") {
sortedBy { it.path }.forEach { println(indent + it.relativeTo(rootProject.projectDir)) }
}
sourceSets.all {
for (configName in listOf(compileOnlyConfigurationName, compileClasspathConfigurationName)) {
configurations.getByName(configName).resolutionStrategy.dependencySubstitution {
all(::configureSubstitution)
}
}
}
}
tasks.register("findShadowJarsInClasspath") {
doLast {
fun Collection<File>.printSorted(indent: String = " ") {
sortedBy { it.path }.forEach { println(indent + it.relativeTo(rootProject.projectDir)) }
}
val mainJars = hashSetOf<File>()
val shadowJars = hashSetOf<File>()
for (project in rootProject.allprojects) {
project.withJavaPlugin {
project.sourceSets.forEach { sourceSet ->
val jarTask = project.tasks.findByPath(sourceSet.jarTaskName) as? Jar
jarTask?.outputFile?.let { mainJars.add(it) }
val shadowJars = hashSetOf<File>()
for (project in rootProject.allprojects) {
for (task in project.tasks) {
when (task) {
is ShadowJar -> {
shadowJars.add(fileFrom(task.archivePath))
}
}
for (task in project.tasks) {
when (task) {
is ShadowJar -> {
shadowJars.add(fileFrom(task.outputFile))
}
is ProGuardTask -> {
shadowJars.addAll(task.outputs.files.toList())
}
is ProGuardTask -> {
shadowJars.addAll(task.outputs.files.toList())
}
}
}
}
shadowJars.removeAll(mainJars)
println("Shadow jars that might break incremental compilation:")
shadowJars.printSorted()
println("Shadow jars:")
shadowJars.printSorted()
fun Project.checkConfig(configName: String) {
val config = configurations.findByName(configName) ?: return
val shadowJarsInConfig = config.resolvedConfiguration.files.filter { it in shadowJars }
if (shadowJarsInConfig.isNotEmpty()) {
println()
println("Project $project contains shadow jars in configuration '$configName':")
shadowJarsInConfig.printSorted()
}
}
for (project in rootProject.allprojects) {
project.sourceSetsOrNull?.forEach { sourceSet ->
project.checkConfig(sourceSet.compileClasspathConfigurationName)
}
fun Project.checkConfig(configName: String) {
val config = configurations.findByName(configName) ?: return
val shadowJarsInConfig = config.resolvedConfiguration.files.filter { it in shadowJars }
if (shadowJarsInConfig.isNotEmpty()) {
println()
println("Project $project contains shadow jars in configuration '$configName':")
shadowJarsInConfig.printSorted()
}
}
for (project in rootProject.allprojects) {
project.checkConfig("compileClasspath")
project.checkConfig("testCompileClasspath")
}
}
val Jar.outputFile: File
get() = archiveFile.get().asFile
val Project.sourceSetsOrNull: SourceSetContainer?
get() = convention.findPlugin(JavaPluginConvention::class.java)?.sourceSets

View File

@@ -1,45 +1,41 @@
import java.util.Properties
extra["versions.shadow"] = "4.0.3"
extra["versions.native-platform"] = "0.14"
buildscript {
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
extra["defaultSnapshotVersion"] = kotlinBuildProperties.defaultSnapshotVersion
BootstrapOption.BintrayBootstrap("1.4.0-dev-1818", cacheRedirectorEnabled).applyToProject(project)
// kotlinBootstrapFrom(BootstrapOption.BintrayBootstrap(kotlinBuildProperties.kotlinBootstrapVersion!!, cacheRedirectorEnabled))
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?)
repositories {
if (cacheRedirectorEnabled) {
maven("https://cache-redirector.jetbrains.com/jcenter.bintray.com")
maven("https://cache-redirector.jetbrains.com/kotlin.bintray.com/kotlin-dependencies")
} else {
jcenter()
maven("https://kotlin.bintray.com/kotlin-dependencies")
}
project.bootstrapKotlinRepo?.let {
buildSrcKotlinRepo?.let {
maven(url = it)
}
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:${project.bootstrapKotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$buildSrcKotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:$buildSrcKotlinVersion")
}
}
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
logger.info("buildSrcKotlinVersion: " + extra["bootstrapKotlinVersion"])
logger.info("buildSrcKotlinVersion: " + extra["buildSrcKotlinVersion"])
logger.info("buildSrc kotlin compiler version: " + org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
logger.info("buildSrc stdlib version: " + KotlinVersion.CURRENT)
apply {
plugin("kotlin")
plugin("kotlin-sam-with-receiver")
from("../gradle/checkCacheability.gradle.kts")
}
plugins {
@@ -49,6 +45,10 @@ plugins {
gradlePlugin {
plugins {
register("pill-configurable") {
id = "pill-configurable"
implementationClass = "org.jetbrains.kotlin.pill.PillConfigurablePlugin"
}
register("jps-compatible") {
id = "jps-compatible"
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatiblePlugin"
@@ -66,46 +66,43 @@ rootProject.apply {
from(rootProject.file("../gradle/versions.gradle.kts"))
}
val isTeamcityBuild = kotlinBuildProperties.isTeamcityBuild
val intellijUltimateEnabled by extra(kotlinBuildProperties.intellijUltimateEnabled)
val flags = LocalBuildProperties(project)
val isTeamcityBuild = flags.isTeamcityBuild
val intellijUltimateEnabled by extra(flags.intellijUltimateEnabled)
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
val verifyDependencyOutput by extra( getBooleanProperty("kotlin.build.dependency.output.verification") ?: isTeamcityBuild)
extra["intellijReleaseType"] = when {
extra["versions.intellijSdk"]?.toString()?.contains("-EAP-") == true -> "snapshots"
extra["versions.intellijSdk"]?.toString()?.endsWith("SNAPSHOT") == true -> "nightly"
else -> "releases"
}
extra["intellijReleaseType"] = if (extra["versions.intellijSdk"]?.toString()?.endsWith("SNAPSHOT") == true)
"snapshots"
else
"releases"
extra["versions.androidDxSources"] = "5.0.0_r2"
extra["customDepsOrg"] = "kotlin.build"
repositories {
jcenter()
maven("https://jetbrains.bintray.com/intellij-third-party-dependencies/")
maven("https://kotlin.bintray.com/kotlin-dependencies")
gradlePluginPortal()
maven("https://plugins.gradle.org/m2/")
jcenter()
extra["bootstrapKotlinRepo"]?.let {
extra["buildSrcKotlinRepo"]?.let {
maven(url = it)
}
}
dependencies {
implementation(kotlin("stdlib", embeddedKotlinVersion))
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
compile(kotlin("stdlib", embeddedKotlinVersion))
compile("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
compile("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
compile("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}")
compile("com.jakewharton.dex:dex-method-list:3.0.0")
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
implementation("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
implementation("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}")
implementation("com.jakewharton.dex:dex-method-list:3.0.0")
compile("com.github.jengelman.gradle.plugins:shadow:${property("versions.shadow")}")
compile("org.jetbrains.intellij.deps:asm-all:7.0.1")
implementation("com.github.jengelman.gradle.plugins:shadow:${rootProject.extra["versions.shadow"]}")
implementation("net.sf.proguard:proguard-gradle:6.2.2")
implementation("org.jetbrains.intellij.deps:asm-all:7.0.1")
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")
compile("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")
}
samWithReceiver {
@@ -115,11 +112,6 @@ samWithReceiver {
fun Project.`samWithReceiver`(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit =
extensions.configure("samWithReceiver", configure)
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks["build"].dependsOn(":prepare-deps:build")
allprojects {
@@ -129,3 +121,30 @@ allprojects {
apply(from = "$rootDir/../gradle/cacheRedirector.gradle.kts")
}
}
// TODO: hide these classes in special gradle plugin for kotlin-ultimate which will support local.properties
class LocalBuildPropertiesProvider(private val project: Project) {
private val localProperties: Properties = Properties()
val rootProjectDir: File = project.rootProject.rootDir.parentFile
init {
rootProjectDir.resolve("local.properties").takeIf { it.isFile }?.let {
it.reader().use(localProperties::load)
}
}
fun getString(name: String): String? = project.findProperty(name)?.toString() ?: localProperties[name]?.toString()
fun getBoolean(name: String): Boolean = getString(name)?.toBoolean() == true
}
class LocalBuildProperties(project: Project) {
val propertiesProvider = LocalBuildPropertiesProvider(project)
val isTeamcityBuild = propertiesProvider.getString("teamcity") != null || System.getenv("TEAMCITY_VERSION") != null
val intellijUltimateEnabled =
(propertiesProvider.getBoolean("intellijUltimateEnabled") || isTeamcityBuild)
&& propertiesProvider.rootProjectDir.resolve("kotlin-ultimate").exists()
}

View File

@@ -9,9 +9,6 @@ import java.text.SimpleDateFormat
import java.util.*
import javax.xml.stream.XMLOutputFactory
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
plugins {
base
}
@@ -68,23 +65,6 @@ repositories {
artifact()
}
}
ivy {
url = URI("https://dl.bintray.com/kotlin/as/")
patternLayout {
artifact("[artifact]-[revision]-$androidStudioOs.[ext]")
}
credentials {
username = System.getenv("AS_BINTRAY_USER_NAME") ?: findProperty("bintray.user") as String?
password = System.getenv("AS_BINTRAY_API_KEY") ?: findProperty("bintray.apikey") as String?
}
metadataSources {
artifact()
}
}
}
maven("https://www.jetbrains.com/intellij-repository/$intellijReleaseType")
@@ -107,18 +87,14 @@ val nodeJSPlugin by configurations.creating
*/
val intellijRuntimeAnnotations = "intellij-runtime-annotations"
val dependenciesDir = (findProperty("kotlin.build.dependencies.dir") as String?)?.let(::File)
?: rootProject.gradle.gradleUserHomeDir.resolve("kotlin-build-dependencies")
val customDepsRepoDir = dependenciesDir.resolve("repo")
val customDepsRepoDir = rootProject.rootDir.parentFile.resolve("dependencies/repo")
val customDepsOrg: String by rootProject.extra
val customDepsRevision = intellijVersion
val repoDir = File(customDepsRepoDir, customDepsOrg)
dependencies {
if (androidStudioRelease != null) {
val extension = if (androidStudioOs == "linux")
val extension = if (androidStudioOs == "linux" && androidStudioRelease.startsWith("3.5"))
"tar.gz"
else
"zip"
@@ -145,29 +121,14 @@ dependencies {
}
}
val makeIntellijCore = buildIvyRepositoryTask(intellijCore, customDepsOrg, customDepsRepoDir)
val cleanupIntellijCore = tasks.register<CleanDataTask>("cleanupIntellijCore") {
cleanableStoreProvider = provider { CleanableStore[repoDir.resolve("intellij-core").absolutePath] }
}
val cleanupIntellijAnnotation = tasks.register<CleanDataTask>("cleanupIntellijAnnotation") {
cleanableStoreProvider = provider { CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath] }
}
val cleanupDependencies = tasks.register("cleanupDependencies") {
dependsOn(cleanupIntellijCore)
dependsOn(cleanupIntellijAnnotation)
}
val makeIntellijCore = buildIvyRepositoryTaskAndRegisterCleanupTask(intellijCore, customDepsOrg, customDepsRepoDir)
val makeIntellijAnnotations by tasks.registering(Copy::class) {
val makeIntellijAnnotations by tasks.creating(Copy::class.java) {
dependsOn(makeIntellijCore)
val intellijCoreRepo = CleanableStore[repoDir.resolve("intellij-core").absolutePath][intellijVersion].use()
from(intellijCoreRepo.resolve("artifacts/annotations.jar"))
from(repoDir.resolve("intellij-core/$intellijVersion/artifacts/annotations.jar"))
val targetDir = CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath][intellijVersion].use()
val targetDir = File(repoDir, "$intellijRuntimeAnnotations/$intellijVersion")
into(targetDir)
val ivyFile = File(targetDir, "$intellijRuntimeAnnotations.ivy.xml")
@@ -189,8 +150,6 @@ val makeIntellijAnnotations by tasks.registering(Copy::class) {
val mergeSources by tasks.creating(Jar::class.java) {
dependsOn(sources)
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
from(provider { sources.map(::zipTree) })
destinationDirectory.set(File(repoDir, sources.name))
archiveBaseName.set("intellij")
@@ -201,20 +160,20 @@ val mergeSources by tasks.creating(Jar::class.java) {
val sourcesFile = mergeSources.outputs.files.singleFile
val makeIde = if (androidStudioBuild != null) {
buildIvyRepositoryTaskAndRegisterCleanupTask(
buildIvyRepositoryTask(
androidStudio,
customDepsOrg,
customDepsRepoDir,
if (androidStudioOs == "mac")
::skipContentsDirectory
else
::skipContentsDirectory
else
::skipToplevelDirectory
)
} else {
val task = if (installIntellijUltimate) {
buildIvyRepositoryTaskAndRegisterCleanupTask(intellijUltimate, customDepsOrg, customDepsRepoDir, null, sourcesFile)
buildIvyRepositoryTask(intellijUltimate, customDepsOrg, customDepsRepoDir, null, sourcesFile)
} else {
buildIvyRepositoryTaskAndRegisterCleanupTask(intellij, customDepsOrg, customDepsRepoDir, null, sourcesFile)
buildIvyRepositoryTask(intellij, customDepsOrg, customDepsRepoDir, null, sourcesFile)
}
task.configure {
@@ -224,7 +183,8 @@ val makeIde = if (androidStudioBuild != null) {
task
}
val buildJpsStandalone = buildIvyRepositoryTaskAndRegisterCleanupTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
val buildJpsStandalone = buildIvyRepositoryTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
val buildNodeJsPlugin = buildIvyRepositoryTask(nodeJSPlugin, customDepsOrg, customDepsRepoDir, ::skipToplevelDirectory, sourcesFile)
tasks.named("build") {
dependsOn(
@@ -234,131 +194,105 @@ tasks.named("build") {
makeIntellijAnnotations
)
if (installIntellijUltimate) {
dependsOn(buildNodeJsPlugin)
}
}
if (installIntellijUltimate) {
val buildNodeJsPlugin =
buildIvyRepositoryTaskAndRegisterCleanupTask(nodeJSPlugin, customDepsOrg, customDepsRepoDir, ::skipToplevelDirectory, sourcesFile)
tasks.named("build") { dependsOn(buildNodeJsPlugin) }
}
tasks.named("build") { dependsOn(cleanupDependencies) }
// Task to delete legacy repo locations
tasks.register<Delete>("cleanLegacy") {
tasks.create("cleanLegacy", Delete::class.java) {
delete("$projectDir/android-dx")
delete("$projectDir/intellij-sdk")
}
tasks.named<Delete>("clean") {
//TODO specify repos to clean? Use CleanDataTask
delete(customDepsRepoDir)
}
fun buildIvyRepositoryTaskAndRegisterCleanupTask(
fun buildIvyRepositoryTask(
configuration: Configuration,
organization: String,
repoDirectory: File,
pathRemap: ((String) -> String)? = null,
sources: File? = null
): TaskProvider<Task> {
fun ResolvedArtifact.storeDirectory(): CleanableStore =
CleanableStore[repoDirectory.resolve("$organization/${moduleVersion.id.name}").absolutePath]
) = tasks.register("buildIvyRepositoryFor${configuration.name.capitalize()}") {
fun ResolvedArtifact.moduleDirectory(): File =
storeDirectory()[moduleVersion.id.version].use()
File(repoDirectory, "$organization/${moduleVersion.id.name}/${moduleVersion.id.version}")
val buildIvyRepositoryTask = tasks.register("buildIvyRepositoryFor${configuration.name.capitalize()}") {
dependsOn(configuration)
inputs.files(configuration)
dependsOn(configuration)
inputs.files(configuration)
if (verifyDependencyOutput) {
outputs.dir(
provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().moduleDirectory()
if (verifyDependencyOutput) {
outputs.dir(provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().moduleDirectory()
})
} else {
outputs.upToDateWhen {
configuration.resolvedConfiguration.resolvedArtifacts.single()
.moduleDirectory()
.exists()
}
}
doFirst {
configuration.resolvedConfiguration.resolvedArtifacts.single().run {
val moduleDirectory = moduleDirectory()
val artifactsDirectory = File(moduleDirectory(), "artifacts")
logger.info("Unpacking ${file.name} into ${artifactsDirectory.absolutePath}")
copy {
val fileTree = when (extension) {
"tar.gz" -> tarTree(file)
"zip" -> zipTree(file)
else -> error("Unsupported artifact extension: $extension")
}
from(fileTree.matching {
exclude("**/plugins/Kotlin/**")
})
into(artifactsDirectory)
if (pathRemap != null) {
eachFile {
path = pathRemap(path)
}
}
includeEmptyDirs = false
}
writeIvyXml(
organization,
moduleVersion.id.name,
moduleVersion.id.version,
moduleVersion.id.name,
File(artifactsDirectory, "lib"),
File(artifactsDirectory, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
} else {
outputs.upToDateWhen {
configuration.resolvedConfiguration.resolvedArtifacts.single()
.moduleDirectory()
.exists()
}
}
doFirst {
configuration.resolvedConfiguration.resolvedArtifacts.single().run {
val moduleDirectory = moduleDirectory()
val artifactsDirectory = File(moduleDirectory(), "artifacts")
logger.info("Unpacking ${file.name} into ${artifactsDirectory.absolutePath}")
copy {
val fileTree = when (extension) {
"tar.gz" -> tarTree(file)
"zip" -> zipTree(file)
else -> error("Unsupported artifact extension: $extension")
val pluginsDirectory = File(artifactsDirectory, "plugins")
if (pluginsDirectory.exists()) {
file(File(artifactsDirectory, "plugins"))
.listFiles { file: File -> file.isDirectory }
.forEach {
writeIvyXml(
organization,
it.name,
moduleVersion.id.version,
it.name,
File(it, "lib"),
File(it, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
}
from(
fileTree.matching {
exclude("**/plugins/Kotlin/**")
}
)
into(artifactsDirectory)
if (pathRemap != null) {
eachFile {
path = pathRemap(path)
}
}
includeEmptyDirs = false
}
writeIvyXml(
organization,
moduleVersion.id.name,
moduleVersion.id.version,
moduleVersion.id.name,
File(artifactsDirectory, "lib"),
File(artifactsDirectory, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
val pluginsDirectory = File(artifactsDirectory, "plugins")
if (pluginsDirectory.exists()) {
file(File(artifactsDirectory, "plugins"))
.listFiles { file: File -> file.isDirectory }
.forEach {
writeIvyXml(
organization,
it.name,
moduleVersion.id.version,
it.name,
File(it, "lib"),
File(it, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
}
}
}
}
}
val cleanupIvyRepositoryTask = tasks.register<CleanDataTask>("cleanupIvyRepositoryFor${configuration.name.capitalize()}") {
cleanableStoreProvider = provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().storeDirectory()
}
}
cleanupDependencies {
dependsOn(cleanupIvyRepositoryTask)
}
return buildIvyRepositoryTask
}
fun writeIvyXml(
@@ -404,24 +338,24 @@ fun writeIvyXml(
}
element("publications") {
artifactDir.listFiles()
?.filter(::shouldIncludeIntellijJar)
?.sortedBy { it.name.toLowerCase() }
?.forEach { jarFile ->
val relativeName = jarFile.toRelativeString(baseDir).removeSuffix(".jar")
emptyElement("artifact") {
attributes(
"name" to relativeName,
"type" to "jar",
"ext" to "jar",
"conf" to "default"
)
}
artifactDir.listFiles()?.filter(::shouldIncludeIntellijJar)?.forEach { jarFile ->
val relativeName = jarFile.toRelativeString(baseDir).removeSuffix(".jar")
emptyElement("artifact") {
attributes(
"name" to relativeName,
"type" to "jar",
"ext" to "jar",
"conf" to "default"
)
}
}
sourcesJar.forEach { jarFile ->
emptyElement("artifact") {
val sourcesArtifactName = jarFile.name.substringBefore("-$version")
val sourcesArtifactName = jarFile.name
.substringBeforeLast("-")
.substringBeforeLast("-")
attributes(
"name" to sourcesArtifactName,
"type" to "jar",

View File

@@ -11,64 +11,54 @@ pluginManagement {
}
}
buildscript {
repositories {
if (cacheRedirectorEnabled == 'true') {
maven { url "https://cache-redirector.jetbrains.com/kotlin.bintray.com/kotlin-dependencies" }
} else {
maven { url "https://kotlin.bintray.com/kotlin-dependencies" }
include "prepare-deps"
def flags = new LocalBuildProperties(settings as Settings)
if (flags.includeCidrPlugins) {
logger.info("Including CIDR plugins in buildSrc/settings.gradle")
include ":prepare-deps:kotlin-native-platform-deps"
project(":prepare-deps:kotlin-native-platform-deps").projectDir = file("${flags.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/kotlin-native-platform-deps")
} else {
logger.info("NOT including CIDR plugins in buildSrc/settings.gradle")
}
class LocalBuildPropertiesProvider {
private Settings settings
private Properties localProperties = new Properties()
File rootProjectDir
LocalBuildPropertiesProvider(Settings settings) {
this.settings = settings
this.rootProjectDir = settings.rootProject.projectDir.parentFile
File propertiesFile = new File(rootProjectDir, 'local.properties')
if (propertiesFile.isFile()) {
propertiesFile.withInputStream { localProperties.load(it) }
}
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
String getString(String name) {
if (settings.hasProperty(name)) {
return settings[name]?.toString()
} else {
return localProperties[name]?.toString()
}
}
Boolean getBoolean(String name) {
return Boolean.parseBoolean(getString(name))
}
}
def buildProperties = BuildPropertiesKt.getKotlinBuildPropertiesForSettings(settings)
def projectVersions = file("../gradle/versions.properties").text
class LocalBuildProperties {
LocalBuildPropertiesProvider propertiesProvider
boolean includeCidrPlugins
BuildCacheKt.setupBuildCache(settings)
include "prepare-deps"
def target_AppCode_Clion = buildProperties.includeCidrPlugins && !projectVersions.contains("versions.androidStudioRelease")
def target_AndroidStudio = buildProperties.includeCidrPlugins && projectVersions.contains("versions.androidStudioRelease")
def target_IdeaUltimate = buildProperties.includeUltimate
if (target_AppCode_Clion) {
logger.info("Including modules for AC and CL in buildSrc/settings.gradle")
include ":prepare-deps:kotlin-native-platform-deps"
include ":prepare-deps:native-debug-plugin"
project(":prepare-deps:kotlin-native-platform-deps").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/kotlin-native-platform-deps")
project(":prepare-deps:native-debug-plugin").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/native-debug-plugin")
} else if (target_AndroidStudio) {
logger.info("Including modules for AS (mobile plugin) in buildSrc/settings.gradle")
include ":prepare-deps:cocoa-common-binaries"
include ":prepare-deps:lldb-framework"
include ":prepare-deps:lldb-frontend"
project(":prepare-deps:cocoa-common-binaries").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/cocoa-common-binaries")
project(":prepare-deps:lldb-framework").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-framework")
project(":prepare-deps:lldb-frontend").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-frontend")
} else if (target_IdeaUltimate) {
logger.info("Including modules for IU in buildSrc/settings.gradle")
include ":prepare-deps:lldb-frontend"
include ":prepare-deps:native-debug-plugin"
project(":prepare-deps:lldb-frontend").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-frontend")
project(":prepare-deps:native-debug-plugin").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/native-debug-plugin")
} else {
logger.info("Not including extra modules in buildSrc/settings.gradle")
}
LocalBuildProperties(Settings settings) {
propertiesProvider = new LocalBuildPropertiesProvider(settings)
includeCidrPlugins = propertiesProvider.getBoolean('cidrPluginsEnabled') && new File(propertiesProvider.rootProjectDir, 'kotlin-ultimate').exists()
}
}

View File

@@ -0,0 +1,85 @@
@file:Suppress("unused") // usages in build scripts are not tracked properly
import org.gradle.api.Project
import org.gradle.kotlin.dsl.*
var Project.bootstrapKotlinVersion: String
get() = this.property("bootstrapKotlinVersion") as String
private set(value) { this.extra["bootstrapKotlinVersion"] = value }
var Project.bootstrapKotlinRepo: String?
get() = this.property("bootstrapKotlinRepo") as String?
private set(value) { this.extra["bootstrapKotlinRepo"] = value }
val Project.internalKotlinRepo: String?
get() = bootstrapKotlinRepo?.replace("artifacts/content/maven/", "artifacts/content/internal/repo")
fun Project.kotlinBootstrapFrom(defaultSource: BootstrapOption) {
val customVersion = project.findProperty("bootstrap.kotlin.version") as String?
val customRepo = project.findProperty("bootstrap.kotlin.repo") as String?
val teamCityVersion = project.findProperty("bootstrap.teamcity.kotlin.version") as String?
val teamCityBuild = project.findProperty("bootstrap.teamcity.build.number") as String?
val teamCityProject = project.findProperty("bootstrap.teamcity.project") as String?
val bootstrapSource = when {
project.hasProperty("bootstrap.local") -> BootstrapOption.Local(project.findProperty("bootstrap.local.version") as String?, project.findProperty("bootstrap.local.path") as String?)
teamCityVersion != null -> BootstrapOption.TeamCity(teamCityVersion, teamCityBuild, projectExtId = teamCityProject, onlySuccessBootstrap = false)
customVersion != null -> BootstrapOption.Custom(kotlinVersion = customVersion, repo = customRepo)
else -> defaultSource
}
bootstrapSource.applyToProject(project)
project.logger.lifecycle("Using kotlin bootstrap version $bootstrapKotlinVersion from repo $bootstrapKotlinRepo")
}
sealed class BootstrapOption {
abstract fun applyToProject(project: Project)
/** Manual repository and version specification.
*
* If [repo] is not specified the default buildscript and project repositories are used
*/
open class Custom(val kotlinVersion: String, val repo: String?) : BootstrapOption() {
override fun applyToProject(project: Project) {
project.bootstrapKotlinVersion = kotlinVersion
project.bootstrapKotlinRepo = repo
}
}
/** Get bootstrap from kotlin-dev bintray repo, where bootstraps are published */
class BintrayDev(kotlinVersion: String) : Custom(kotlinVersion, "https://dl.bintray.com/kotlin/kotlin-dev")
/** Get bootstrap from teamcity maven artifacts of the specified build configuration
*
* [kotlinVersion] the version of maven artifacts
* [buildNumber] build number of a teamcity build, by default the same as [kotlinVersion],
* [projectExtId] extId of a teamcity build configuration, by default "Kotlin_dev_Compiler",
* [onlySuccessBootstrap] allow artifacts only from success builds of the default branch tagged with 'bootstrap' tag
*/
class TeamCity(val kotlinVersion: String, val buildNumber: String? = null, val projectExtId: String? = null, val onlySuccessBootstrap: Boolean = true) : BootstrapOption() {
override fun applyToProject(project: Project) {
val query = if (onlySuccessBootstrap) "status:SUCCESS,tag:bootstrap,pinned:true" else "branch:default:any"
project.bootstrapKotlinRepo = "https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:${projectExtId ?: "Kotlin_dev_Compiler"}),number:${buildNumber ?: kotlinVersion},$query/artifacts/content/maven/"
project.bootstrapKotlinVersion = kotlinVersion
}
}
/**
* Use previously published local artifacts from the build/repo maven repository
*
* [kotlinVersion] version of artifacts, by default the snapshot version of project is used
* [localPath] the path to local repository, if specified it is resolved with respect or project dir
*/
class Local(val kotlinVersion: String? = null, val localPath: String? = null) : BootstrapOption() {
override fun applyToProject(project: Project) {
val repoPath = if (localPath != null)
project.projectDir.resolve(localPath).canonicalFile
else
project.buildDir.resolve("repo")
project.bootstrapKotlinRepo = repoPath.toURI().toString()
project.bootstrapKotlinVersion = kotlinVersion ?: project.property("defaultSnapshotVersion") as String
}
}
}

View File

@@ -1,18 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
val KotlinBuildProperties.includeJava9: Boolean
get() = !isInJpsBuildIdeaSync && getBoolean("kotlin.build.java9", true)
val KotlinBuildProperties.useBootstrapStdlib: Boolean
get() = isInJpsBuildIdeaSync || getBoolean("kotlin.build.useBootstrapStdlib", false)
val KotlinBuildProperties.postProcessing: Boolean get() = isTeamcityBuild || getBoolean("kotlin.build.postprocessing", true)
val KotlinBuildProperties.relocation: Boolean get() = postProcessing
val KotlinBuildProperties.proguard: Boolean get() = postProcessing && getBoolean("kotlin.build.proguard", isTeamcityBuild)
val KotlinBuildProperties.jarCompression: Boolean get() = getBoolean("kotlin.build.jar.compression", isTeamcityBuild)

View File

@@ -1,385 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
import groovy.lang.Closure
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.*
import org.gradle.internal.jvm.Jvm
import org.gradle.internal.jvm.inspection.JvmVersionDetector
import proguard.ClassSpecification
import java.io.File
import javax.inject.Inject
@CacheableTask
open class CacheableProguardTask @Inject constructor(
private val jvmVersionDetector: JvmVersionDetector
) : proguard.gradle.ProGuardTask() {
@Internal
var jdkHome: File? = null
@get:Optional
@get:Input
internal val jdkMajorVersion: String?
get() = jdkHome?.let { jvmVersionDetector.getJavaVersion(Jvm.forHome(jdkHome)) }?.majorVersion
@CompileClasspath
override fun getLibraryJarFileCollection(): FileCollection = super.getLibraryJarFileCollection().filter { libraryFile ->
jdkHome?.let { !libraryFile.absoluteFile.startsWith(it.absoluteFile) } ?: true
}
@InputFiles
@PathSensitive(PathSensitivity.RELATIVE)
override fun getConfigurationFileCollection(): FileCollection = super.getConfigurationFileCollection()
@InputFiles
@Classpath
override fun getInJarFileCollection(): FileCollection = super.getInJarFileCollection()
@Optional
@OutputFiles
override fun getOutJarFileCollection(): FileCollection = super.getOutJarFileCollection()
@get:Optional
@get:OutputFile
internal val printConfigurationFile: File?
get() = configuration.printConfiguration?.takeIf { it.path.isNotEmpty() }
@Input
override fun getOutJarFilters(): MutableList<Any?> = super.getOutJarFilters()
@Input
override fun getInJarFilters(): MutableList<Any?> = super.getInJarFilters()
@Input
override fun getLibraryJarFilters(): MutableList<Any?> = super.getLibraryJarFilters()
@Internal
override fun getOutJarFiles(): MutableList<Any?> = super.getOutJarFiles()
@Internal
override fun getInJarFiles(): MutableList<Any?> = super.getInJarFiles()
@Internal
override fun getInJarCounts(): MutableList<Any?> = super.getInJarCounts()
@Internal
override fun getLibraryJarFiles(): MutableList<Any?> = super.getLibraryJarFiles()
/*
* Inputs properly declared these methods so we don't override them
*
* configuration(configurationFiles: Any?)
* libraryjars(libraryJarFiles: Any?)
* libraryjars(filterArgs: MutableMap<Any?, Any?>?, libraryJarFiles: Any?)
* injars(inJarFiles: Any?)
* injars(filterArgs: MutableMap<Any?, Any?>?, inJarFiles: Any?)
* outjars(outJarFiles: Any?)
* outjars(filterArgs: MutableMap<Any?, Any?>?, outJarFiles: Any?)
* printconfiguration()
* printconfiguration(printConfiguration: Any?)
*/
override fun renamesourcefileattribute() = throw NotImplementedError()
override fun renamesourcefileattribute(newSourceFileAttribute: String?) = throw NotImplementedError()
override fun dontshrink() = throw NotImplementedError()
override fun assumenosideeffects(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenosideeffects(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun keepnames(classSpecificationString: String?) = throw NotImplementedError()
override fun keepnames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepnames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepnames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun printmapping() = throw NotImplementedError()
override fun printmapping(printMapping: Any?) = throw NotImplementedError()
override fun keep(classSpecificationString: String?) = throw NotImplementedError()
override fun keep(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keep(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keep(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun keepdirectories() = throw NotImplementedError()
override fun keepdirectories(filter: String?) = throw NotImplementedError()
override fun dontpreverify() = throw NotImplementedError()
override fun dontnote() = throw NotImplementedError()
override fun dontnote(filter: String?) = throw NotImplementedError()
@Internal
override fun getrenamesourcefileattribute(): Any? = throw NotImplementedError()
override fun useuniqueclassmembernames() = throw NotImplementedError()
override fun overloadaggressively() = throw NotImplementedError()
@Internal
override fun getprintusage(): Any? = throw NotImplementedError()
@Internal
override fun getforceprocessing(): Any? = throw NotImplementedError()
override fun whyareyoukeeping(classSpecificationString: String?) = throw NotImplementedError()
override fun whyareyoukeeping(classSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun whyareyoukeeping(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun obfuscationdictionary(obfuscationDictionary: Any?) = throw NotImplementedError()
override fun adaptclassstrings() = throw NotImplementedError()
override fun adaptclassstrings(filter: String?) = throw NotImplementedError()
override fun applymapping(applyMapping: Any?) = throw NotImplementedError()
override fun mergeinterfacesaggressively() = throw NotImplementedError()
@Internal
override fun getdontwarn(): Any? = throw NotImplementedError()
override fun ignorewarnings() = throw NotImplementedError()
@Internal
override fun getaddconfigurationdebugging(): Any? = throw NotImplementedError()
override fun field(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
@Internal
override fun getallowaccessmodification(): Any? = throw NotImplementedError()
override fun constructor(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun dontusemixedcaseclassnames() = throw NotImplementedError()
@Internal
override fun getignorewarnings(): Any? = throw NotImplementedError()
@Internal
override fun getkeepdirectories(): Any? = throw NotImplementedError()
override fun classobfuscationdictionary(classObfuscationDictionary: Any?) = throw NotImplementedError()
override fun verbose() = throw NotImplementedError()
override fun optimizations(filter: String?) = throw NotImplementedError()
@Internal
override fun getuseuniqueclassmembernames(): Any? = throw NotImplementedError()
@Internal
override fun getmicroedition(): Any? = throw NotImplementedError()
override fun assumenoescapingparameters(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenoescapingparameters(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getandroid(): Any? = throw NotImplementedError()
override fun keeppackagenames() = throw NotImplementedError()
override fun keeppackagenames(filter: String?) = throw NotImplementedError()
@Internal
override fun getoverloadaggressively(): Any? = throw NotImplementedError()
override fun skipnonpubliclibraryclasses() = throw NotImplementedError()
@Internal
override fun getdontusemixedcaseclassnames(): Any? = throw NotImplementedError()
@Internal
override fun getdontnote(): Any? = throw NotImplementedError()
override fun assumenoexternalreturnvalues(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenoexternalreturnvalues(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun target(targetClassVersion: String?) = throw NotImplementedError()
override fun keepattributes() = throw NotImplementedError()
override fun keepattributes(filter: String?) = throw NotImplementedError()
override fun keepclassmembernames(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembernames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclassmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getdontpreverify(): Any? = throw NotImplementedError()
@Internal
override fun getverbose(): Any? = throw NotImplementedError()
@Internal
override fun getskipnonpubliclibraryclasses(): Any? = throw NotImplementedError()
@Internal
override fun getdontoptimize(): Any? = throw NotImplementedError()
override fun keepclasseswithmembernames(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembernames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclasseswithmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun keepclasseswithmembers(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembers(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclasseswithmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getdump(): Any? = throw NotImplementedError()
override fun printseeds() = throw NotImplementedError()
override fun printseeds(printSeeds: Any?) = throw NotImplementedError()
override fun dontoptimize() = throw NotImplementedError()
override fun dontobfuscate() = throw NotImplementedError()
override fun extendClassSpecifications(
classSpecifications: MutableList<Any?>?,
classSpecification: ClassSpecification?
): MutableList<Any?> = throw NotImplementedError()
override fun allowaccessmodification() = throw NotImplementedError()
@Internal
override fun getdontobfuscate(): Any? = throw NotImplementedError()
@Internal
override fun getprintmapping(): Any? = throw NotImplementedError()
override fun flattenpackagehierarchy() = throw NotImplementedError()
override fun flattenpackagehierarchy(flattenPackageHierarchy: String?) = throw NotImplementedError()
override fun android() = throw NotImplementedError()
override fun dump() = throw NotImplementedError()
override fun dump(dump: Any?) = throw NotImplementedError()
@Internal
override fun getdontshrink(): Any? = throw NotImplementedError()
@Internal
override fun getkeepattributes(): Any? = throw NotImplementedError()
override fun microedition() = throw NotImplementedError()
override fun keepparameternames() = throw NotImplementedError()
override fun addconfigurationdebugging() = throw NotImplementedError()
override fun packageobfuscationdictionary(packageObfuscationDictionary: Any?) = throw NotImplementedError()
@Internal
override fun getdontskipnonpubliclibraryclassmembers(): Any? = throw NotImplementedError()
override fun dontskipnonpubliclibraryclassmembers() = throw NotImplementedError()
@Internal
override fun getprintconfiguration(): Any? = throw NotImplementedError()
override fun forceprocessing() = throw NotImplementedError()
override fun keepclassmembers(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembers(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclassmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getmergeinterfacesaggressively(): Any? = throw NotImplementedError()
@Internal
override fun getConfigurationFiles(): MutableList<Any?> = throw NotImplementedError()
@Internal
override fun getkeeppackagenames(): Any? = throw NotImplementedError()
override fun assumevalues(classSpecificationString: String?) = throw NotImplementedError()
override fun assumevalues(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun printusage() = throw NotImplementedError()
override fun printusage(printUsage: Any?) = throw NotImplementedError()
@Internal
override fun getprintseeds(): Any? = throw NotImplementedError()
@Internal
override fun getadaptresourcefilenames(): Any? = throw NotImplementedError()
override fun assumenoexternalsideeffects(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenoexternalsideeffects(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun dontwarn() = throw NotImplementedError()
override fun dontwarn(filter: String?) = throw NotImplementedError()
@Internal
override fun getrepackageclasses(): Any? = throw NotImplementedError()
@Internal
override fun getadaptresourcefilecontents(): Any? = throw NotImplementedError()
@Internal
override fun getflattenpackagehierarchy(): Any? = throw NotImplementedError()
override fun optimizationpasses(optimizationPasses: Int) = throw NotImplementedError()
override fun adaptresourcefilenames() = throw NotImplementedError()
override fun adaptresourcefilenames(filter: String?) = throw NotImplementedError()
override fun method(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
@Internal
override fun getadaptclassstrings(): Any? = throw NotImplementedError()
override fun repackageclasses() = throw NotImplementedError()
override fun repackageclasses(repackageClasses: String?) = throw NotImplementedError()
@Internal
override fun getkeepparameternames(): Any? = throw NotImplementedError()
override fun adaptresourcefilecontents() = throw NotImplementedError()
override fun adaptresourcefilecontents(filter: String?) = throw NotImplementedError()
}

View File

@@ -7,18 +7,16 @@ import org.gradle.api.Task
import org.gradle.api.file.CopySourceSpec
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.SourceSetOutput
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.kotlin.dsl.*
import proguard.gradle.ProGuardTask
import org.gradle.kotlin.dsl.creating
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.the
import java.io.File
import java.util.concurrent.Callable
inline fun <reified T : Task> Project.task(noinline configuration: T.() -> Unit) = tasks.registering(T::class, configuration)
inline fun <reified T : Task> Project.eagerTask(noinline configuration: T.() -> Unit) = tasks.creating(T::class, configuration)
inline fun <reified T : Task> Project.task(noinline configuration: T.() -> Unit) = tasks.creating(T::class, configuration)
fun Project.callGroovy(name: String, vararg args: Any?): Any? {
return (property(name) as Closure<*>).call(*args)
@@ -58,7 +56,6 @@ fun Project.generator(fqName: String, sourceSet: SourceSet? = null) = smartJavaE
classpath = (sourceSet ?: testSourceSet).runtimeClasspath
main = fqName
workingDir = rootDir
systemProperty("line.separator", "\n")
}
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
@@ -70,13 +67,3 @@ fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)
inline fun CopySourceSpec.from(crossinline filesProvider: () -> Any?): CopySourceSpec = from(Callable { filesProvider() })
fun Project.javaPluginConvention(): JavaPluginConvention = the()
fun Project.findJavaPluginConvention(): JavaPluginConvention? = convention.findByType() ?: convention.findPlugin()
fun JavaExec.pathRelativeToWorkingDir(file: File): String = file.relativeTo(workingDir).invariantSeparatorsPath
fun Task.singleOutputFile(): File = when (this) {
is AbstractArchiveTask -> archiveFile.get().asFile
is ProGuardTask -> project.file(outJarFiles.single()!!)
else -> outputs.files.singleFile
}

View File

@@ -26,7 +26,7 @@ fun CompatibilityPredicate.or(other: CompatibilityPredicate): CompatibilityPredi
}
enum class Platform : CompatibilityPredicate {
P183, P191, P192, P193, P201;
P181, P182, P183, P191, P192;
val version: Int = name.drop(1).toInt()
@@ -41,14 +41,16 @@ enum class Platform : CompatibilityPredicate {
}
enum class Ide(val platform: Platform) : CompatibilityPredicate {
IJ181(Platform.P181),
IJ182(Platform.P182),
IJ183(Platform.P183),
IJ191(Platform.P191),
IJ192(Platform.P192),
IJ193(Platform.P193),
IJ201(Platform.P201),
AS35(Platform.P183),
AS36(Platform.P192),
AS40(Platform.P193);
AS32(Platform.P181),
AS33(Platform.P182),
AS34(Platform.P183),
AS35(Platform.P183);
val kind = Kind.values().first { it.shortName == name.take(2) }
val version = name.dropWhile { !it.isDigit() }.toInt()

View File

@@ -1,7 +1,6 @@
import org.gradle.api.Project
import org.gradle.api.tasks.JavaExec
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.creating
import org.gradle.kotlin.dsl.task
/*
@@ -9,8 +8,7 @@ import org.gradle.kotlin.dsl.task
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// creating class eagerly here: using register causes problems due to quite complicated relationships between these tasks
fun Project.smartJavaExec(configure: JavaExec.() -> Unit) = tasks.creating(JavaExec::class) {
fun Project.smartJavaExec(configure: JavaExec.() -> Unit) = task<JavaExec> {
configure()
passClasspathInJar()
}

View File

@@ -8,12 +8,17 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.AbstractCopyTask
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.*
import java.io.File
private const val MAGIC_DO_NOT_CHANGE_TEST_JAR_TASK_NAME = "testJar"
@@ -47,11 +52,11 @@ fun Project.removeArtifacts(configuration: Configuration, task: Task) {
}
fun Project.noDefaultJar() {
tasks.named("jar").configure {
enabled = false
actions = emptyList()
tasks.findByName("jar")?.let { defaultJarTask ->
defaultJarTask.enabled = false
defaultJarTask.actions = emptyList()
configurations.forEach { cfg ->
removeArtifacts(cfg, this)
removeArtifacts(cfg, defaultJarTask)
}
}
}
@@ -64,13 +69,12 @@ fun Project.runtimeJarArtifactBy(task: Task, artifactRef: Any, body: Configurabl
}
}
fun Project.runtimeJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> = runtimeJar(getOrCreateTask("jar", body), { })
fun <T : Jar> Project.runtimeJar(task: TaskProvider<T>, body: T.() -> Unit = {}): TaskProvider<T> {
tasks.named<Jar>("jar").configure {
removeArtifacts(configurations.getOrCreate("archives"), this)
fun <T : Jar> Project.runtimeJar(task: T, body: T.() -> Unit = {}): T {
extra["runtimeJarTask"] = task
tasks.findByName("jar")?.let { defaultJarTask ->
removeArtifacts(configurations.getOrCreate("archives"), defaultJarTask)
}
task.configure {
return task.apply {
configurations.findByName("embedded")?.let { embedded ->
dependsOn(embedded)
from {
@@ -82,9 +86,10 @@ fun <T : Jar> Project.runtimeJar(task: TaskProvider<T>, body: T.() -> Unit = {})
body()
project.runtimeJarArtifactBy(this, this)
}
return task
}
fun Project.runtimeJar(body: Jar.() -> Unit = {}): Jar = runtimeJar(getOrCreateTask("jar", body), { })
fun Project.sourcesJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
val task = tasks.register<Jar>("sourcesJar") {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
@@ -98,12 +103,7 @@ fun Project.sourcesJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
.resolvedArtifacts
.map { it.id.componentIdentifier }
.filterIsInstance<ProjectComponentIdentifier>()
.mapNotNull {
project(it.projectPath)
.findJavaPluginConvention()
?.mainSourceSet
?.allSource
}
.map { project(it.projectPath).mainSourceSet.allSource }
})
}
@@ -116,19 +116,15 @@ fun Project.sourcesJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
return task
}
fun Project.javadocJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
val javadocTask = getOrCreateTask<Jar>("javadocJar") {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
archiveClassifier.set("javadoc")
tasks.findByName("javadoc")?.let { it as Javadoc }?.takeIf { it.enabled }?.let {
dependsOn(it)
from(it.destinationDir)
}
body()
fun Project.javadocJar(body: Jar.() -> Unit = {}): Jar = getOrCreateTask("javadocJar") {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
classifier = "javadoc"
tasks.findByName("javadoc")?.let { it as Javadoc }?.takeIf { it.enabled }?.let {
dependsOn(it)
from(it.destinationDir)
}
addArtifact("archives", javadocTask)
return javadocTask
body()
project.addArtifact("archives", this, this)
}
@@ -155,6 +151,11 @@ fun Project.publish(body: Upload.() -> Unit = {}): Upload {
}
}
private fun Project.runtimeJarTaskIfExists(): Task? =
if (extra.has("runtimeJarTask")) extra["runtimeJarTask"] as Task
else tasks.findByName("jar")
fun ConfigurationContainer.getOrCreate(name: String): Configuration = findByName(name) ?: create(name)
fun Jar.setupPublicJar(baseName: String, classifier: String = "") {

View File

@@ -0,0 +1,115 @@
import org.gradle.api.Project
import org.gradle.api.initialization.Settings
import org.gradle.api.internal.DynamicObjectAware
import java.io.File
import java.util.*
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
interface PropertiesProvider {
val rootProjectDir: File
fun getProperty(key: String): Any?
}
class KotlinBuildProperties(
private val propertiesProvider: PropertiesProvider
) {
private val localProperties: Properties = Properties()
init {
val localPropertiesFile = propertiesProvider.rootProjectDir.resolve("local.properties")
if (localPropertiesFile.isFile) {
localPropertiesFile.reader().use(localProperties::load)
}
}
private operator fun get(key: String): Any? = localProperties.getProperty(key) ?: propertiesProvider.getProperty(key)
private fun getBoolean(key: String, default: Boolean = false): Boolean =
(this[key]?.toString()?.toBoolean() ?: default) == true
val isJpsBuildEnabled: Boolean = getBoolean("jpsBuild")
val isInIdeaSync: Boolean = run {
// "idea.sync.active" was introduced in 2019.1
System.getProperty("idea.sync.active")?.toBoolean() == true || let {
// before 2019.1 there is "idea.active" that was true only on sync,
// but since 2019.1 "idea.active" present in task execution too.
// So let's check Idea version
val majorIdeaVersion = System.getProperty("idea.version")
?.split(".")
?.getOrNull(0)
val isBeforeIdea2019 = majorIdeaVersion == null || majorIdeaVersion.toInt() < 2019
isBeforeIdea2019 && System.getProperty("idea.active")?.toBoolean() == true
}
}
val isInJpsBuildIdeaSync: Boolean
get() = isJpsBuildEnabled && isInIdeaSync
val includeJava9: Boolean
get() = !isInJpsBuildIdeaSync && getBoolean("kotlin.build.java9", true)
val useBootstrapStdlib: Boolean
get() = isInJpsBuildIdeaSync || getBoolean("kotlin.build.useBootstrapStdlib", false)
val kotlinUltimateExists: Boolean = propertiesProvider.rootProjectDir.resolve("kotlin-ultimate").exists()
val includeCidrPlugins: Boolean = kotlinUltimateExists && getBoolean("cidrPluginsEnabled")
val isTeamcityBuild: Boolean = getBoolean("teamcity") || System.getenv("TEAMCITY_VERSION") != null
val intellijUltimateEnabled: Boolean
get() {
val explicitlyEnabled = getBoolean("intellijUltimateEnabled")
if (!kotlinUltimateExists && explicitlyEnabled) {
error("intellijUltimateEnabled property is set, while kotlin-ultimate repository is not provided")
}
return kotlinUltimateExists && (explicitlyEnabled || isTeamcityBuild)
}
val postProcessing: Boolean get() = isTeamcityBuild || getBoolean("kotlin.build.postprocessing", true)
val relocation: Boolean get() = postProcessing
val proguard: Boolean get() = postProcessing && getBoolean("kotlin.build.proguard", isTeamcityBuild)
val jsIrDist: Boolean get() = getBoolean("kotlin.stdlib.js.ir.dist")
}
private const val extensionName = "kotlinBuildProperties"
class ProjectProperties(val project: Project) : PropertiesProvider {
override val rootProjectDir: File
get() = project.projectDir
override fun getProperty(key: String): Any? = project.findProperty(key)
}
val Project.kotlinBuildProperties: KotlinBuildProperties
get() = rootProject.extensions.findByName(extensionName) as KotlinBuildProperties?
?: KotlinBuildProperties(ProjectProperties(rootProject)).also {
rootProject.extensions.add(extensionName, it)
}
class SettingsProperties(val settings: Settings) : PropertiesProvider {
override val rootProjectDir: File
get() = settings.rootDir
override fun getProperty(key: String): Any? {
val obj = (settings as DynamicObjectAware).asDynamicObject
return if (obj.hasProperty(key)) obj.getProperty(key) else null
}
}
fun getKotlinBuildPropertiesForSettings(settings: Any) = (settings as Settings).kotlinBuildProperties
val Settings.kotlinBuildProperties: KotlinBuildProperties
get() = extensions.findByName(extensionName) as KotlinBuildProperties?
?: KotlinBuildProperties(SettingsProperties(this)).also {
extensions.add(extensionName, it)
}

View File

@@ -2,25 +2,20 @@
// usages in build scripts are not tracked properly
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.AbstractCopyTask
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.project
import java.io.File
private val Project.isEAPIntellij get() = rootProject.extra["versions.intellijSdk"].toString().contains("-EAP-")
private val Project.isNightlyIntellij get() = rootProject.extra["versions.intellijSdk"].toString().endsWith("SNAPSHOT") && !isEAPIntellij
val Project.isSnapshotIntellij get() = rootProject.extra["versions.intellijSdk"].toString().endsWith("SNAPSHOT")
val Project.intellijRepo get() =
when {
isEAPIntellij -> "https://www.jetbrains.com/intellij-repository/snapshots"
isNightlyIntellij -> "https://www.jetbrains.com/intellij-repository/nightly"
else -> "https://www.jetbrains.com/intellij-repository/releases"
}
val Project.intellijRepo get() = "https://www.jetbrains.com/intellij-repository/" + if (isSnapshotIntellij) "snapshots" else "releases"
fun Project.commonDep(coord: String): String {
val parts = coord.split(':')
@@ -133,15 +128,7 @@ fun Project.firstFromJavaHomeThatExists(vararg paths: String, jdkHome: File = Fi
logger.warn("Cannot find file by paths: ${paths.toList()} in $jdkHome")
}
fun Project.toolsJarApi(): Any =
if (kotlinBuildProperties.isInJpsBuildIdeaSync)
files(toolsJarFile() ?: error("tools.jar is not found!"))
else
dependencies.project(":dependencies:tools-jar-api")
fun Project.toolsJar(): FileCollection = files(toolsJarFile() ?: error("tools.jar is not found!"))
fun Project.toolsJarFile(jdkHome: File = File(this.property("JDK_18") as String)): File? =
fun Project.toolsJar(jdkHome: File = File(this.property("JDK_18") as String)): File? =
firstFromJavaHomeThatExists("lib/tools.jar", jdkHome = jdkHome)
val compilerManifestClassPath

View File

@@ -3,8 +3,8 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.tasks.TaskProvider
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.task
import org.gradle.kotlin.dsl.*
import java.io.File
@@ -19,9 +19,7 @@ val packagesToRelocate =
"org.picocontainer",
"org.jline",
"org.fusesource",
"kotlinx.coroutines",
"net.jpountz",
"one.util.streamex")
"kotlinx.coroutines")
// The shaded compiler "dummy" is used to rewrite dependencies in projects that are used with the embeddable compiler
// on the runtime and use some shaded dependencies from the compiler
@@ -59,12 +57,12 @@ private fun ShadowJar.configureEmbeddableCompilerRelocation(withJavaxInject: Boo
}
}
private fun Project.compilerShadowJar(taskName: String, body: ShadowJar.() -> Unit): TaskProvider<out ShadowJar> {
private fun Project.compilerShadowJar(taskName: String, body: ShadowJar.() -> Unit): Jar {
val compilerJar = configurations.getOrCreate("compilerJar")
dependencies.add(compilerJar.name, dependencies.project(":kotlin-compiler", configuration = "runtimeJar"))
return tasks.register<ShadowJar>(taskName) {
return task<ShadowJar>(taskName) {
destinationDir = File(buildDir, "libs")
setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE)
from(compilerJar)
@@ -72,39 +70,31 @@ private fun Project.compilerShadowJar(taskName: String, body: ShadowJar.() -> Un
}
}
fun Project.embeddableCompiler(taskName: String = "embeddable", body: ShadowJar.() -> Unit = {}): TaskProvider<out ShadowJar> =
compilerShadowJar(taskName) {
configureEmbeddableCompilerRelocation()
body()
}
fun Project.embeddableCompiler(taskName: String = "embeddable", body: ShadowJar.() -> Unit = {}): Jar =
compilerShadowJar(taskName) {
configureEmbeddableCompilerRelocation()
body()
}
fun Project.compilerDummyForDependenciesRewriting(
taskName: String = "compilerDummy", body: ShadowJar.() -> Unit = {}
): TaskProvider<out Jar> =
compilerShadowJar(taskName) {
exclude(packagesToExcludeFromDummy)
body()
}
fun Project.compilerDummyForDependenciesRewriting(taskName: String = "compilerDummy", body: ShadowJar.() -> Unit = {}): Jar =
compilerShadowJar(taskName) {
exclude(packagesToExcludeFromDummy)
body()
}
const val COMPILER_DUMMY_JAR_CONFIGURATION_NAME = "compilerDummyJar"
fun Project.compilerDummyJar(task: TaskProvider<out Jar>, body: Jar.() -> Unit = {}) {
task.configure(body)
task.configure {
addArtifact(COMPILER_DUMMY_JAR_CONFIGURATION_NAME, this, this)
}
fun Project.compilerDummyJar(task: Jar, body: Jar.() -> Unit = {}) {
task.body()
addArtifact(COMPILER_DUMMY_JAR_CONFIGURATION_NAME, task, task)
}
fun Project.embeddableCompilerDummyForDependenciesRewriting(
taskName: String = "embeddable", body: Jar.() -> Unit = {}
): TaskProvider<ShadowJar> {
fun Project.embeddableCompilerDummyForDependenciesRewriting(taskName: String = "embeddable", body: Jar.() -> Unit = {}): Jar {
val compilerDummyJar = configurations.getOrCreate("compilerDummyJar")
dependencies.add(
compilerDummyJar.name,
dependencies.project(":kotlin-compiler-embeddable", configuration = COMPILER_DUMMY_JAR_CONFIGURATION_NAME)
)
dependencies.add(compilerDummyJar.name,
dependencies.project(":kotlin-compiler-embeddable", configuration = COMPILER_DUMMY_JAR_CONFIGURATION_NAME))
return tasks.register<ShadowJar>(taskName) {
return task<ShadowJar>(taskName) {
destinationDir = File(buildDir, "libs")
setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE)
from(compilerDummyJar)
@@ -113,16 +103,14 @@ fun Project.embeddableCompilerDummyForDependenciesRewriting(
}
}
fun Project.rewriteDepsToShadedJar(
originalJarTask: TaskProvider<out Jar>, shadowJarTask: TaskProvider<out Jar>, body: Jar.() -> Unit = {}
): TaskProvider<out Jar> {
originalJarTask.configure {
fun Project.rewriteDepsToShadedJar(originalJarTask: Jar, shadowJarTask: Jar, body: Jar.() -> Unit = {}): Jar {
originalJarTask.apply {
classifier = "original"
}
val compilerDummyJarFile by lazy { configurations.getAt("compilerDummyJar").singleFile }
shadowJarTask.configure {
return shadowJarTask.apply {
dependsOn(originalJarTask)
from(originalJarTask)// { include("**") }
@@ -133,11 +121,7 @@ fun Project.rewriteDepsToShadedJar(
classifier = ""
body()
}
return shadowJarTask
}
fun Project.rewriteDepsToShadedCompiler(originalJarTask: TaskProvider<out Jar>, body: Jar.() -> Unit = {}): TaskProvider<out Jar> =
rewriteDepsToShadedJar(originalJarTask, embeddableCompilerDummyForDependenciesRewriting(), body)
fun Project.rewriteDefaultJarDepsToShadedCompiler(body: Jar.() -> Unit = {}): TaskProvider<out Jar> =
rewriteDepsToShadedJar(tasks.named<Jar>("jar"), embeddableCompilerDummyForDependenciesRewriting(), body)
fun Project.rewriteDepsToShadedCompiler(originalJarTask: Jar, body: Jar.() -> Unit = {}): Jar =
rewriteDepsToShadedJar(originalJarTask, embeddableCompilerDummyForDependenciesRewriting(), body)

View File

@@ -44,29 +44,10 @@ fun Project.configureFormInstrumentation() {
// classes from the "friendly directory" to the compile classpath.
val testCompile = tasks.findByName("compileTestKotlin") as AbstractCompile?
testCompile?.doFirst {
val originalClassesDirs = files((mainSourceSet as ExtensionAware).extra.get("classesDirsCopy"))
testCompile.classpath = (testCompile.classpath
- mainSourceSet.output.classesDirs
+ originalClassesDirs)
// Since Kotlin 1.3.60, the friend paths available to the test compile task are calculated as the main source set's
// output.classesDirs. Since the classesDirs are excluded from the classpath (replaced by the originalClassesDirs),
// in order to be able to access the internals of 'main', tests need to receive the original classes dirs as a
// -Xfriend-paths compiler argument as well.
fun addFreeCompilerArgs(kotlinCompileTask: AbstractCompile, vararg args: String) {
val getKotlinOptions = kotlinCompileTask::class.java.getMethod("getKotlinOptions")
val kotlinOptions = getKotlinOptions(kotlinCompileTask)
val getFreeCompilerArgs = kotlinOptions::class.java.getMethod("getFreeCompilerArgs")
val freeCompilerArgs = getFreeCompilerArgs(kotlinOptions) as List<*>
val setFreeCompilerArgs = kotlinOptions::class.java.getMethod("setFreeCompilerArgs", List::class.java)
setFreeCompilerArgs(kotlinOptions, freeCompilerArgs + args)
}
addFreeCompilerArgs(testCompile, "-Xfriend-paths=" + originalClassesDirs.joinToString(",") { it.absolutePath })
+ files((mainSourceSet as ExtensionAware).extra.get("classesDirsCopy")))
}
}
val instrumentationClasspathCfg = configurations.create("instrumentationClasspath")
@@ -87,15 +68,16 @@ fun Project.configureFormInstrumentation() {
val instrumentedClassesDir = File(project.buildDir, "classes/${sourceSetParam.name}-instrumented")
(sourceSetParam.output.classesDirs as ConfigurableFileCollection).setFrom(instrumentedClassesDir)
val instrumentTask =
project.tasks.register(sourceSetParam.getTaskName("instrument", "classes"), IntelliJInstrumentCodeTask::class.java) {
dependsOn(sourceSetParam.classesTaskName).onlyIf { !classesDirsCopy.isEmpty }
sourceSet = sourceSetParam
instrumentationClasspath = instrumentationClasspathCfg
originalClassesDirs = classesDirsCopy
output = instrumentedClassesDir
outputs.dir(instrumentedClassesDir)
}
project.tasks.create(sourceSetParam.getTaskName("instrument", "classes"), IntelliJInstrumentCodeTask::class.java)
instrumentTask.apply {
dependsOn(sourceSetParam.classesTaskName).onlyIf { !classesDirsCopy.isEmpty }
sourceSet = sourceSetParam
instrumentationClasspath = instrumentationClasspathCfg
originalClassesDirs = classesDirsCopy
output = instrumentedClassesDir
}
instrumentTask.outputs.dir(instrumentedClassesDir)
// Ensure that our task is invoked when the source set is built
sourceSetParam.compiledBy(instrumentTask)
@Suppress("UNUSED_EXPRESSION")
@@ -111,21 +93,17 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
private const val LOADER_REF = "java2.loader"
}
@Classpath
var sourceSet: SourceSet? = null
var instrumentationClasspath: Configuration? = null
@InputFiles
@PathSensitive(PathSensitivity.RELATIVE)
@Input
var originalClassesDirs: FileCollection? = null
@get:Input
var instrumentNotNull: Boolean = false
@Internal
var sourceSet: SourceSet? = null
@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
val sourceDirs: FileCollection
get() = project.files(sourceSet!!.allSource.srcDirs.filter { !sourceSet!!.resources.contains(it) && it.exists() })

View File

@@ -4,7 +4,6 @@ import net.rubygrapefruit.platform.Native
import net.rubygrapefruit.platform.WindowsRegistry
import org.gradle.api.GradleException
import org.gradle.api.Project
import java.nio.file.Paths
import java.io.File
import net.rubygrapefruit.platform.WindowsRegistry.Key.HKEY_LOCAL_MACHINE
import org.gradle.internal.os.OperatingSystem
@@ -26,7 +25,7 @@ fun Project.getConfiguredJdks(): List<JdkId> {
?: System.getenv(jdkMajorVersion.name)
?: jdkAlternativeVarNames[jdkMajorVersion]?.mapNotNull { System.getenv(it) }?.firstOrNull()
?: continue
val explicitJdk = Paths.get(explicitJdkEnvVal).toRealPath().toFile()
val explicitJdk = File(explicitJdkEnvVal)
if (!explicitJdk.isDirectory) {
throw GradleException("Invalid environment value $jdkMajorVersion: $explicitJdkEnvVal, expecting JDK home path")
}

View File

@@ -23,17 +23,10 @@ import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.DependencyHandlerScope
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.*
import java.io.File
private fun Project.kotlinBuildLocalDependenciesDir(): File =
(findProperty("kotlin.build.dependencies.dir") as String?)?.let(::File)
?: rootProject.gradle.gradleUserHomeDir.resolve("kotlin-build-dependencies")
private fun Project.kotlinBuildLocalRepoDir(): File = kotlinBuildLocalDependenciesDir().resolve("repo")
private fun Project.kotlinBuildLocalRepoDir() = File("${project.rootDir.absoluteFile}/dependencies/repo")
private fun Project.ideModuleName() = when (IdeVersionConfigurator.currentIde.kind) {
Ide.Kind.AndroidStudio -> "android-studio-ide"
@@ -158,9 +151,9 @@ fun DependencyHandlerScope.excludeInAndroidStudio(rootProject: Project, block: D
}
}
fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File, body: JavaExec.() -> Unit): TaskProvider<JavaExec> {
fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File, body: JavaExec.() -> Unit): JavaExec {
return tasks.register<JavaExec>(name) {
return task<JavaExec>(name) {
val ideaSandboxConfigDir = File(ideaSandboxDir, "config")
classpath = mainSourceSet.runtimeClasspath
@@ -183,10 +176,6 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
"-Dplugin.path=${ideaPluginDir.absolutePath}"
)
if (Platform[201].orHigher()) {
jvmArgs("-Didea.platform.prefix=Idea")
}
if (rootProject.findProperty("versions.androidStudioRelease") != null) {
jvmArgs("-Didea.platform.prefix=AndroidStudio")
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Plugin
import org.gradle.api.Project
@Suppress("unused")
class JpsCompatiblePlugin : Plugin<Project> {
override fun apply(project: Project) {
project.configurations.maybeCreate(EmbeddedComponents.CONFIGURATION_NAME)
project.extensions.create("pill", PillExtension::class.java)
// 'jpsTest' does not require the 'tests-jar' artifact
project.configurations.create("jpsTest")
if (project == project.rootProject) {
project.tasks.create("pill") {
dependsOn(":pill:pill-importer:pill")
if (System.getProperty("pill.android.tests", "false") == "true") {
TaskUtils.useAndroidSdk(this)
TaskUtils.useAndroidJar(this)
}
}
project.tasks.create("unpill") {
dependsOn(":pill:pill-importer:unpill")
}
}
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
import org.gradle.api.Project
open class PillExtension {
enum class Variant {
// Default variant (./gradlew pill)
BASE() {
override val includes = setOf(BASE)
},
// Full variant (./gradlew pill -Dpill.variant=full)
FULL() {
override val includes = setOf(BASE, FULL)
},
// Do not import the project to JPS model, but set some options for it
NONE() {
override val includes = emptySet<Variant>()
},
// 'BASE' if the "jps-compatible" plugin is applied, 'NONE' otherwise
DEFAULT() {
override val includes = emptySet<Variant>()
};
abstract val includes: Set<Variant>
}
open var variant: Variant = Variant.DEFAULT
open var excludedDirs: List<File> = emptyList()
@Suppress("unused")
fun Project.excludedDirs(vararg dirs: String) {
excludedDirs = excludedDirs + dirs.map { File(projectDir, it) }
}
@Suppress("unused")
fun serialize() = mapOf<String, Any?>(
"variant" to variant.name,
"excludedDirs" to excludedDirs
)
}

View File

@@ -0,0 +1,33 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.component.*
class DependencyMapper(val predicate: (ResolvedArtifact) -> Boolean, val mapping: (ResolvedArtifact) -> MappedDependency?) {
companion object {
fun forProject(path: String, mapping: (ResolvedArtifact) -> MappedDependency?): DependencyMapper {
return DependencyMapper(
predicate = { artifact ->
val identifier = artifact.id.componentIdentifier as? ProjectComponentIdentifier
identifier?.projectPath == path
},
mapping = mapping
)
}
fun forModule(group: String, module: String, version: String?, mapping: (ResolvedArtifact) -> MappedDependency?): DependencyMapper {
return DependencyMapper(
predicate = { artifact ->
val identifier = artifact.id.componentIdentifier as? ModuleComponentIdentifier
identifier?.group == group && identifier?.module == module && (version == null || identifier?.version == version)
},
mapping = mapping
)
}
}
}
class MappedDependency(val main: PDependency?, val deferred: List<PDependency> = emptyList())
class ParserContext(val dependencyMappers: List<DependencyMapper>, val variant: PillExtension.Variant)

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
import org.gradle.api.Project
import org.gradle.api.tasks.SourceSet
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.component.*
data class PDependencies(val main: List<PDependency>, val deferred: List<PDependency>) {
fun join(): List<PDependency> {
return main + deferred
}
}
fun Project.resolveDependencies(
configuration: Configuration,
forTests: Boolean,
dependencyMappers: List<DependencyMapper>,
withEmbedded: Boolean = false
): PDependencies {
val dependencies = mutableListOf<PDependency>()
val deferred = mutableListOf<PDependency>()
nextArtifact@ for (artifact in configuration.resolvedConfiguration.resolvedArtifacts) {
val identifier = artifact.id.componentIdentifier
for (mapper in dependencyMappers) {
if (mapper.predicate(artifact)) {
val mapped = mapper.mapping(artifact)
if (mapped != null) {
mapped.main?.let { dependencies += it }
deferred += mapped.deferred
}
continue@nextArtifact
}
}
fun addProjectDependency(projectPath: String) {
val project = rootProject.findProject(projectPath) ?: error("Cannot find project $projectPath")
fun addSourceSet(name: String, suffix: String): Boolean {
val sourceSet = project.sourceSets?.findByName(name)?.takeIf { !it.allSource.isEmpty() } ?: return false
dependencies += PDependency.Module(project.pillModuleName + '.' + suffix)
return true
}
if (forTests && artifact.classifier == "tests") {
addSourceSet(SourceSet.TEST_SOURCE_SET_NAME, "test") || addSourceSet(SourceSet.MAIN_SOURCE_SET_NAME, "src")
} else {
addSourceSet(SourceSet.MAIN_SOURCE_SET_NAME, "src")
}
if (withEmbedded) {
val embeddedConfiguration = project.configurations.findByName(EmbeddedComponents.CONFIGURATION_NAME)
if (embeddedConfiguration != null) {
dependencies += resolveDependencies(embeddedConfiguration, forTests, dependencyMappers, withEmbedded).join()
}
}
}
when (identifier) {
is ProjectComponentIdentifier -> addProjectDependency(identifier.projectPath)
is LibraryBinaryIdentifier -> addProjectDependency(identifier.projectPath)
is ModuleComponentIdentifier -> {
val file = artifact.file
val library = PLibrary(file.name, classes = listOf(file))
dependencies += PDependency.ModuleLibrary(library)
}
}
}
val existingFiles = mutableSetOf<File>()
for (dependency in configuration.dependencies) {
if (dependency !is SelfResolvingDependency) {
continue
}
val files = dependency.resolve().filter { it !in existingFiles }.takeIf { it.isNotEmpty() } ?: continue
existingFiles.addAll(files)
val library = PLibrary(dependency.name, classes = files.toList())
deferred += PDependency.ModuleLibrary(library)
}
return PDependencies(dependencies, deferred)
}

View File

@@ -0,0 +1,39 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
import org.gradle.api.Project
open class PillExtension {
enum class Variant {
// Default variant (./gradlew pill)
BASE() { override val includes = setOf(BASE) },
// Full variant (./gradlew pill -Dpill.variant=full)
FULL() { override val includes = setOf(BASE, FULL) },
// Do not import the project to JPS model, but set some options for it
NONE() { override val includes = emptySet<Variant>() },
// 'BASE' if the "jps-compatible" plugin is applied, 'NONE' otherwise
DEFAULT() { override val includes = emptySet<Variant>() };
abstract val includes: Set<Variant>
}
open var variant: Variant = Variant.DEFAULT
open var importAsLibrary: Boolean = false
open var excludedDirs: List<File> = emptyList()
fun Project.excludedDirs(vararg dirs: String) {
excludedDirs = excludedDirs + dirs.map { File(projectDir, it) }
}
open var libraryPath: File? = null
set(v) {
importAsLibrary = true
field = v
}
}

View File

@@ -0,0 +1,182 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.internal.file.copy.SingleParentCopySpec
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.Copy
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.extra
import org.jetbrains.kotlin.pill.ArtifactElement.*
import org.jetbrains.kotlin.pill.POrderRoot.*
import java.io.File
class PArtifact(val artifactName: String, val outputDir: File, private val contents: ArtifactElement.Root) {
fun render(context: PathContext) = xml("component", "name" to "ArtifactManager") {
xml("artifact", "name" to artifactName) {
xml("output-path") {
raw(context(outputDir))
}
add(contents.renderRecursively(context))
}
}
}
sealed class ArtifactElement {
private val myChildren = mutableListOf<ArtifactElement>()
val children get() = myChildren
fun add(child: ArtifactElement) {
myChildren += child
}
fun add(children: List<ArtifactElement>) {
myChildren += children
}
abstract fun render(context: PathContext): xml
fun renderRecursively(context: PathContext): xml {
return render(context).apply {
children.forEach { add(it.renderRecursively(context)) }
}
}
fun getDirectory(path: String): ArtifactElement {
if (path.isEmpty()) {
return this
}
var current: ArtifactElement = this
for (segment in path.split("/")) {
val existing = current.children.firstOrNull { it is Directory && it.name == segment }
if (existing != null) {
current = existing
continue
}
current = Directory(segment).also { current.add(it) }
}
return current
}
class Root : ArtifactElement() {
override fun render(context: PathContext) = xml("root", "id" to "root")
}
data class Directory(val name: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "directory", "name" to name)
}
data class Archive(val name: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "archive", "name" to name)
}
data class ModuleOutput(val moduleName: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "module-output", "name" to moduleName)
}
data class FileCopy(val source: File, val outputFileName: String? = null) : ArtifactElement() {
override fun render(context: PathContext): xml {
val args = mutableListOf("id" to "file-copy", "path" to context(source))
if (outputFileName != null) {
args += "output-file-name" to outputFileName
}
return xml("element", *args.toTypedArray())
}
}
data class DirectoryCopy(val source: File) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "dir-copy", "path" to context(source))
}
data class ProjectLibrary(val name: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "library", "level" to "project", "name" to name)
}
data class ExtractedDirectory(val archive: File, val pathInJar: String = "/") : ArtifactElement() {
override fun render(context: PathContext) =
xml("element", "id" to "extracted-dir", "path" to context(archive), "path-in-jar" to pathInJar)
}
}
fun generateKotlinPluginArtifactFile(rootProject: Project, dependencyMappers: List<DependencyMapper>): PFile {
val root = Root()
fun Project.getProject(name: String) = findProject(name) ?: error("Cannot find project $name")
val prepareIdeaPluginProject = rootProject.getProject(":prepare:idea-plugin")
root.add(Directory("kotlinc").apply {
val kotlincDirectory = rootProject.extra["distKotlinHomeDir"].toString()
add(DirectoryCopy(File(kotlincDirectory)))
})
root.add(Directory("lib").apply {
val librariesConfiguration = prepareIdeaPluginProject.configurations.getByName("libraries")
add(getArtifactElements(rootProject, librariesConfiguration, dependencyMappers, false))
add(Directory("jps").apply {
val prepareJpsPluginProject = rootProject.getProject(":kotlin-jps-plugin")
add(Archive(prepareJpsPluginProject.name + ".jar").apply {
val jpsPluginConfiguration = prepareIdeaPluginProject.configurations.getByName("jpsPlugin")
add(getArtifactElements(rootProject, jpsPluginConfiguration, dependencyMappers, true))
})
})
add(Archive("kotlin-plugin.jar").apply {
add(FileCopy(File(rootProject.projectDir, "resources/kotlinManifest.properties")))
val embeddedConfiguration = prepareIdeaPluginProject.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME)
add(getArtifactElements(rootProject, embeddedConfiguration, dependencyMappers, true))
})
})
val artifact = PArtifact("KotlinPlugin", File(rootProject.projectDir, "out/artifacts/Kotlin"), root)
return PFile(
File(rootProject.projectDir, ".idea/artifacts/${artifact.artifactName}.xml"),
artifact.render(ProjectContext(rootProject))
)
}
private fun getArtifactElements(
rootProject: Project,
configuration: Configuration,
dependencyMappers: List<DependencyMapper>,
extractDependencies: Boolean
): List<ArtifactElement> {
val dependencies = rootProject.resolveDependencies(configuration, false, dependencyMappers, withEmbedded = true).join()
val artifacts = mutableListOf<ArtifactElement>()
for (dependency in dependencies) {
when (dependency) {
is PDependency.Module -> {
val moduleOutput = ModuleOutput(dependency.name)
if (extractDependencies) {
artifacts += moduleOutput
} else {
artifacts += Archive(dependency.name + ".jar").apply {
add(moduleOutput)
}
}
}
is PDependency.Library -> artifacts += ProjectLibrary(dependency.name)
is PDependency.ModuleLibrary -> {
val files = dependency.library.classes
if (extractDependencies) files.mapTo(artifacts) { ExtractedDirectory(it) }
else files.mapTo(artifacts) { FileCopy(it) }
}
}
}
return artifacts
}

View File

@@ -0,0 +1,421 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Project
import org.gradle.api.artifacts.*
import org.gradle.api.tasks.*
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.kotlin.dsl.configure
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.internal.HasConvention
import org.gradle.api.internal.file.copy.CopySpecInternal
import org.gradle.api.internal.file.copy.SingleParentCopySpec
import org.gradle.language.jvm.tasks.ProcessResources
import org.jetbrains.kotlin.pill.POrderRoot.*
import org.jetbrains.kotlin.pill.PSourceRoot.*
import org.jetbrains.kotlin.pill.PillExtension.*
import java.io.File
import java.util.LinkedList
data class PProject(
val name: String,
val rootDirectory: File,
val modules: List<PModule>,
val libraries: List<PLibrary>
)
data class PModule(
val name: String,
val rootDirectory: File,
val moduleFile: File,
val contentRoots: List<PContentRoot>,
val orderRoots: List<POrderRoot>,
val moduleForProductionSources: PModule? = null
)
data class PContentRoot(
val path: File,
val forTests: Boolean,
val sourceRoots: List<PSourceRoot>,
val excludedDirectories: List<File>
)
data class PSourceRoot(
val path: File,
val kind: Kind,
val kotlinOptions: PSourceRootKotlinOptions?
) {
enum class Kind { PRODUCTION, TEST, RESOURCES, TEST_RESOURCES }
}
data class PSourceRootKotlinOptions(
val noStdlib: Boolean?,
val noReflect: Boolean?,
val moduleName: String?,
val apiVersion: String?,
val languageVersion: String?,
val jvmTarget: String?,
val extraArguments: List<String>
) {
fun intersect(other: PSourceRootKotlinOptions) = PSourceRootKotlinOptions(
if (noStdlib == other.noStdlib) noStdlib else null,
if (noReflect == other.noReflect) noReflect else null,
if (moduleName == other.moduleName) moduleName else null,
if (apiVersion == other.apiVersion) apiVersion else null,
if (languageVersion == other.languageVersion) languageVersion else null,
if (jvmTarget == other.jvmTarget) jvmTarget else null,
extraArguments.intersect(other.extraArguments).toList()
)
}
data class POrderRoot(
val dependency: PDependency,
val scope: Scope,
val isExported: Boolean = false,
val isProductionOnTestDependency: Boolean = false
) {
enum class Scope { COMPILE, TEST, RUNTIME, PROVIDED }
}
sealed class PDependency {
data class Module(val name: String) : PDependency()
data class Library(val name: String) : PDependency()
data class ModuleLibrary(val library: PLibrary) : PDependency()
}
data class PLibrary(
val name: String,
val classes: List<File>,
val javadoc: List<File> = emptyList(),
val sources: List<File> = emptyList(),
val annotations: List<File> = emptyList(),
val dependencies: List<PLibrary> = emptyList(),
val originalName: String = name
) {
fun attachSource(file: File): PLibrary {
return this.copy(sources = this.sources + listOf(file))
}
}
fun parse(project: Project, libraries: List<PLibrary>, context: ParserContext): PProject = with (context) {
if (project != project.rootProject) {
error("$project is not a root project")
}
fun Project.matchesSelectedVariant(): Boolean {
val extension = this.extensions.findByType(PillExtension::class.java) ?: return true
val projectVariant = extension.variant.takeUnless { it == Variant.DEFAULT } ?: Variant.BASE
return projectVariant in context.variant.includes
}
val (includedProjects, excludedProjects) = project.allprojects
.partition { it.plugins.hasPlugin(JpsCompatiblePlugin::class.java) && it.matchesSelectedVariant() }
val modules = includedProjects.flatMap { parseModules(it, excludedProjects) }
return PProject("Kotlin", project.projectDir, modules, libraries)
}
/*
Ordering here and below is significant.
Placing 'runtime' configuration dependencies on the top make 'idea' tests to run normally.
('idea' module has 'intellij-core' as transitive dependency, and we really need to get rid of it.)
*/
private val CONFIGURATION_MAPPING = mapOf(
listOf("runtimeClasspath") to Scope.RUNTIME,
listOf("compile", "embedded") to Scope.COMPILE,
listOf("compileOnly") to Scope.PROVIDED
)
private val TEST_CONFIGURATION_MAPPING = mapOf(
listOf("runtimeClasspath", "testRuntimeClasspath") to Scope.RUNTIME,
listOf("compile", "testCompile") to Scope.COMPILE,
listOf("compileOnly", "testCompileOnly") to Scope.PROVIDED,
listOf("jpsTest") to Scope.TEST
)
private fun ParserContext.parseModules(project: Project, excludedProjects: List<Project>): List<PModule> {
val (productionContentRoots, testContentRoots) = parseContentRoots(project).partition { !it.forTests }
val modules = mutableListOf<PModule>()
fun getJavaExcludedDirs() = project.plugins.findPlugin(IdeaPlugin::class.java)
?.model?.module?.excludeDirs?.toList() ?: emptyList()
fun getPillExcludedDirs() = project.extensions.getByType(PillExtension::class.java).excludedDirs
val allExcludedDirs = getPillExcludedDirs() + getJavaExcludedDirs() + project.buildDir +
(if (project == project.rootProject) excludedProjects.map { it.buildDir } else emptyList())
var productionSourcesModule: PModule? = null
fun getModuleFile(suffix: String = ""): File {
val relativePath = File(project.projectDir, project.pillModuleName + suffix + ".iml")
.toRelativeString(project.rootProject.projectDir)
return File(project.rootProject.projectDir, ".idea/modules/$relativePath")
}
for ((nameSuffix, roots) in mapOf(".src" to productionContentRoots, ".test" to testContentRoots)) {
if (roots.isEmpty()) {
continue
}
val mainRoot = roots.first()
var dependencies = parseDependencies(project, mainRoot.forTests)
if (productionContentRoots.isNotEmpty() && mainRoot.forTests) {
val productionModuleDependency = PDependency.Module(project.pillModuleName + ".src")
dependencies += POrderRoot(productionModuleDependency, Scope.COMPILE, true)
}
val module = PModule(
project.pillModuleName + nameSuffix,
mainRoot.path,
getModuleFile(nameSuffix),
roots,
dependencies,
productionSourcesModule
)
modules += module
if (!mainRoot.forTests) {
productionSourcesModule = module
}
}
val mainModuleFileRelativePath = when (project) {
project.rootProject -> File(project.rootProject.projectDir, project.rootProject.name + ".iml")
else -> getModuleFile()
}
modules += PModule(
project.pillModuleName,
project.projectDir,
mainModuleFileRelativePath,
listOf(PContentRoot(project.projectDir, false, emptyList(), allExcludedDirs)),
if (modules.isEmpty()) parseDependencies(project, false) else emptyList()
)
return modules
}
private fun parseContentRoots(project: Project): List<PContentRoot> {
val sourceRoots = parseSourceRoots(project).groupBy { it.kind }
fun getRoots(kind: PSourceRoot.Kind) = sourceRoots[kind] ?: emptyList()
val productionSourceRoots = getRoots(Kind.PRODUCTION) + getRoots(Kind.RESOURCES)
val testSourceRoots = getRoots(Kind.TEST) + getRoots(Kind.TEST_RESOURCES)
fun createContentRoots(sourceRoots: List<PSourceRoot>, forTests: Boolean): List<PContentRoot> {
return sourceRoots.map { PContentRoot(it.path, forTests, listOf(it), emptyList()) }
}
return createContentRoots(productionSourceRoots, forTests = false) +
createContentRoots(testSourceRoots, forTests = true)
}
private fun parseSourceRoots(project: Project): List<PSourceRoot> {
if (!project.plugins.hasPlugin(JavaPlugin::class.java)) {
return emptyList()
}
val kotlinTasksBySourceSet = project.tasks.names
.filter { it.startsWith("compile") && it.endsWith("Kotlin") }
.map { project.tasks.getByName(it) }
.associateBy { it.invokeInternal("getSourceSetName") }
val sourceRoots = mutableListOf<PSourceRoot>()
val sourceSets = project.sourceSets
if (sourceSets != null) {
for (sourceSet in sourceSets) {
val kotlinCompileTask = kotlinTasksBySourceSet[sourceSet.name]
val kind = if (sourceSet.isTestSourceSet) Kind.TEST else Kind.PRODUCTION
fun Any.getKotlin(): SourceDirectorySet {
val kotlinMethod = javaClass.getMethod("getKotlin")
val oldIsAccessible = kotlinMethod.isAccessible
try {
kotlinMethod.isAccessible = true
return kotlinMethod(this) as SourceDirectorySet
} finally {
kotlinMethod.isAccessible = oldIsAccessible
}
}
val kotlinSourceDirectories = (sourceSet as HasConvention).convention
.plugins["kotlin"]?.getKotlin()?.srcDirs
?: emptySet()
val directories = (sourceSet.java.sourceDirectories.files + kotlinSourceDirectories).toList()
.filter { it.exists() }
.takeIf { it.isNotEmpty() }
?: continue
val kotlinOptions = kotlinCompileTask?.let { getKotlinOptions(it) }
for (resourceRoot in sourceSet.resources.sourceDirectories.files) {
if (!resourceRoot.exists() || resourceRoot in directories) {
continue
}
val resourceRootKind = when (kind) {
Kind.PRODUCTION -> Kind.RESOURCES
Kind.TEST -> Kind.TEST_RESOURCES
else -> error("Invalid source root kind $kind")
}
sourceRoots += PSourceRoot(resourceRoot, resourceRootKind, kotlinOptions)
}
for (directory in directories) {
sourceRoots += PSourceRoot(directory, kind, kotlinOptions)
}
for (root in parseResourceRootsProcessedByProcessResourcesTask(project, sourceSet)) {
if (sourceRoots.none { it.path == root.path }) {
sourceRoots += root
}
}
}
}
return sourceRoots
}
private fun parseResourceRootsProcessedByProcessResourcesTask(project: Project, sourceSet: SourceSet): List<PSourceRoot> {
val isMainSourceSet = sourceSet.name == SourceSet.MAIN_SOURCE_SET_NAME
val resourceRootKind = if (sourceSet.isTestSourceSet) PSourceRoot.Kind.TEST_RESOURCES else PSourceRoot.Kind.RESOURCES
val taskNameBase = "processResources"
val taskName = if (isMainSourceSet) taskNameBase else sourceSet.name + taskNameBase.capitalize()
val task = project.tasks.findByName(taskName) as? ProcessResources ?: return emptyList()
val roots = mutableListOf<File>()
fun collectRoots(spec: CopySpecInternal) {
if (spec is SingleParentCopySpec && spec.children.none()) {
roots += spec.sourcePaths.map { File(project.projectDir, it.toString()) }.filter { it.exists() }
return
}
spec.children.forEach(::collectRoots)
}
collectRoots(task.rootSpec)
return roots.map { PSourceRoot(it, resourceRootKind, null) }
}
private val SourceSet.isTestSourceSet: Boolean
get() = name == SourceSet.TEST_SOURCE_SET_NAME
|| name.endsWith("Test")
|| name.endsWith("Tests")
private fun getKotlinOptions(kotlinCompileTask: Any): PSourceRootKotlinOptions? {
val compileArguments = run {
val method = kotlinCompileTask::class.java.getMethod("getSerializedCompilerArguments")
method.isAccessible = true
method.invoke(kotlinCompileTask) as List<String>
}
fun parseBoolean(name: String) = compileArguments.contains("-$name")
fun parseString(name: String) = compileArguments.dropWhile { it != "-$name" }.drop(1).firstOrNull()
fun isOptionForScriptingCompilerPlugin(option: String)
= option.startsWith("-Xplugin=") && option.contains("kotlin-scripting-compiler")
val extraArguments = compileArguments.filter {
it.startsWith("-X") && !isOptionForScriptingCompilerPlugin(it)
}
return PSourceRootKotlinOptions(
parseBoolean("no-stdlib"),
parseBoolean("no-reflect"),
parseString("module-name"),
parseString("api-version"),
parseString("language-version"),
parseString("jvm-target"),
extraArguments
)
}
private fun Any.invokeInternal(name: String, instance: Any = this): Any? {
val method = javaClass.methods.single { it.name.startsWith(name) && it.parameterTypes.isEmpty() }
val oldIsAccessible = method.isAccessible
try {
method.isAccessible = true
return method.invoke(instance)
} finally {
method.isAccessible = oldIsAccessible
}
}
private fun ParserContext.parseDependencies(project: Project, forTests: Boolean): List<POrderRoot> {
val configurations = project.configurations
val configurationMapping = if (forTests) TEST_CONFIGURATION_MAPPING else CONFIGURATION_MAPPING
val mainRoots = mutableListOf<POrderRoot>()
val deferredRoots = mutableListOf<POrderRoot>()
for ((configurationNames, scope) in configurationMapping) {
for (configurationName in configurationNames) {
val configuration = configurations.findByName(configurationName) ?: continue
val (main, deferred) = project.resolveDependencies(configuration, forTests, dependencyMappers)
mainRoots += main.map { POrderRoot(it, scope) }
deferredRoots += deferred.map { POrderRoot(it, scope) }
}
}
return removeDuplicates(mainRoots + deferredRoots)
}
fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
val dependenciesByScope = roots.groupBy { it.scope }.mapValues { it.value.mapTo(mutableSetOf()) { it.dependency } }
fun dependenciesFor(scope: Scope) = dependenciesByScope[scope] ?: emptySet<PDependency>()
val result = mutableSetOf<POrderRoot>()
for (root in roots.distinct()) {
val scope = root.scope
val dependency = root.dependency
if (root in result) {
continue
}
if ((scope == Scope.PROVIDED || scope == Scope.RUNTIME) && dependency in dependenciesFor(Scope.COMPILE)) {
continue
}
if (scope == Scope.PROVIDED && dependency in dependenciesFor(Scope.RUNTIME)) {
result += POrderRoot(dependency, Scope.COMPILE)
continue
}
if (scope == Scope.RUNTIME && dependency in dependenciesFor(Scope.PROVIDED)) {
result += POrderRoot(dependency, Scope.COMPILE)
continue
}
result += root
}
return result.toList()
}
val Project.pillModuleName: String
get() = path.removePrefix(":").replace(':', '.')
val Project.sourceSets: SourceSetContainer?
get() {
val convention = project.convention.findPlugin(JavaPluginConvention::class.java) ?: return null
return convention.sourceSets
}

View File

@@ -0,0 +1,54 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Project
import java.io.File
private val USER_HOME_DIR_PATH = System.getProperty("user.home").withSlash()
private fun replacePrefix(path: String, prefix: String, variableName: String): String {
if (path.startsWith(prefix)) {
return "$" + variableName + "$/" + path.drop(prefix.length)
}
return path
}
private fun simplifyUserHomeDirPath(path: String): String {
return replacePrefix(path, USER_HOME_DIR_PATH, "USER_HOME")
}
interface PathContext {
operator fun invoke(file: File): String
fun url(file: File): Pair<String, String> {
val path = when {
file.isFile && file.extension.toLowerCase() == "jar" -> "jar://" + this(file) + "!/"
else -> "file://" + this(file)
}
return Pair("url", path)
}
}
class ProjectContext private constructor(private val projectDir: File) : PathContext {
constructor(project: PProject) : this(project.rootDirectory)
constructor(project: Project) : this(project.projectDir)
override fun invoke(file: File): String {
return simplifyUserHomeDirPath(replacePrefix(file.absolutePath, projectDir.absolutePath.withSlash(), "PROJECT_DIR"))
}
}
class ModuleContext(val project: PProject, val module: PModule) : PathContext {
override fun invoke(file: File): String {
if (!file.startsWith(project.rootDirectory)) {
return simplifyUserHomeDirPath(file.absolutePath)
}
return "\$MODULE_DIR\$/" + file.toRelativeString(module.moduleFile.parentFile)
}
}
fun String.withSlash() = if (this.endsWith("/")) this else (this + "/")
fun String.withoutSlash() = this.trimEnd('/')

View File

@@ -0,0 +1,336 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.kotlin.dsl.extra
import shadow.org.jdom2.input.SAXBuilder
import shadow.org.jdom2.*
import shadow.org.jdom2.output.Format
import shadow.org.jdom2.output.XMLOutputter
import java.io.File
class PillConfigurablePlugin : Plugin<Project> {
override fun apply(project: Project) {
project.configurations.maybeCreate(EmbeddedComponents.CONFIGURATION_NAME)
project.extensions.create("pill", PillExtension::class.java)
}
}
class JpsCompatiblePlugin : Plugin<Project> {
companion object {
private fun getDependencyMappers(projectLibraries: List<PLibrary>): List<DependencyMapper> {
val mappersForKotlinLibrariesExeptStdlib = projectLibraries
.filter { it.name != "kotlin-stdlib" }
.map { DependencyMapper.forProject(it.originalName) { MappedDependency(PDependency.Library(it.name)) } }
val disabledModuleMappers = listOf(
":kotlin-stdlib-common",
":core:builtins",
":kotlin-compiler",
":kotlin-compiler-embeddable",
":kotlin-test:kotlin-test-common",
":kotlin-test:kotlin-test-annotations-common"
).map { DependencyMapper.forProject(it) { null } }
return listOf(
DependencyMapper.forProject(":kotlin-stdlib") {
MappedDependency(
PDependency.Library("kotlin-stdlib"),
listOf(PDependency.Library("annotations-13.0"))
)
},
DependencyMapper.forProject(":kotlin-test:kotlin-test-jvm") { MappedDependency(PDependency.Library("kotlin-test-jvm")) },
DependencyMapper.forProject(":kotlin-reflect-api") { MappedDependency(PDependency.Library("kotlin-reflect")) }
) + mappersForKotlinLibrariesExeptStdlib + disabledModuleMappers
}
fun getProjectLibraries(rootProject: Project): List<PLibrary> {
val distLibDir = File(rootProject.extra["distLibDir"].toString())
fun distJar(name: String) = File(rootProject.projectDir, "dist/kotlinc/lib/$name.jar")
val libraries = rootProject.allprojects
.mapNotNull { library ->
val libraryExtension = library.extensions.findByType(PillExtension::class.java)
?.takeIf { it.importAsLibrary }
?: return@mapNotNull null
val libraryPath = libraryExtension.libraryPath ?: distLibDir
val archivesBaseName = library.convention.findPlugin(BasePluginConvention::class.java)?.archivesBaseName ?: library.name
fun List<File>.filterExisting() = filter { it.exists() }
PLibrary(
library.name,
classes = listOf(File(libraryPath, "$archivesBaseName.jar")).filterExisting(),
sources = listOf(File(libraryPath, "$archivesBaseName-sources.jar")).filterExisting(),
originalName = library.path
)
}
return libraries + PLibrary("annotations-13.0", classes = listOf(distJar("annotations-13.0")))
}
}
override fun apply(project: Project) {
project.plugins.apply(PillConfigurablePlugin::class.java)
// 'jpsTest' does not require the 'tests-jar' artifact
project.configurations.create("jpsTest")
if (project == project.rootProject) {
project.tasks.create("pill") {
doLast { pill(project) }
if (System.getProperty("pill.android.tests", "false") == "true") {
TaskUtils.useAndroidSdk(this)
TaskUtils.useAndroidJar(this)
}
}
project.tasks.create("unpill") {
doLast { unpill(project) }
}
}
}
private lateinit var projectDir: File
private lateinit var platformVersion: String
private lateinit var platformBaseNumber: String
private lateinit var platformDir: File
private var isAndroidStudioPlatform: Boolean = false
private fun initEnvironment(project: Project) {
projectDir = project.projectDir
platformVersion = project.extensions.extraProperties.get("versions.intellijSdk").toString()
platformBaseNumber = platformVersion.substringBefore(".", "").takeIf { it.isNotEmpty() }
?: platformVersion.substringBefore("-", "").takeIf { it.isNotEmpty() }
?: error("Invalid platform version: $platformVersion")
platformDir = IntellijRootUtils.getIntellijRootDir(project)
isAndroidStudioPlatform = project.extensions.extraProperties.has("versions.androidStudioRelease")
}
private fun pill(rootProject: Project) {
initEnvironment(rootProject)
val variantOptionValue = System.getProperty("pill.variant", "base").toUpperCase()
val variant = PillExtension.Variant.values().firstOrNull { it.name == variantOptionValue }
?: run {
rootProject.logger.error("Invalid variant name: $variantOptionValue")
return
}
rootProject.logger.lifecycle("Pill: Setting up project for the '${variant.name.toLowerCase()}' variant...")
if (variant == PillExtension.Variant.NONE || variant == PillExtension.Variant.DEFAULT) {
rootProject.logger.error("'none' and 'default' should not be passed as a Pill variant property value")
return
}
val projectLibraries = getProjectLibraries(rootProject)
val dependencyMappers = getDependencyMappers(projectLibraries)
val parserContext = ParserContext(dependencyMappers, variant)
val jpsProject = parse(rootProject, projectLibraries, parserContext)
.mapLibraries(this::attachPlatformSources, this::attachAsmSources)
val files = render(jpsProject)
removeExistingIdeaLibrariesAndModules()
removeJpsAndPillRunConfigurations()
removeAllArtifactConfigurations()
generateKotlinPluginArtifactFile(rootProject, dependencyMappers).write()
copyRunConfigurations()
setOptionsForDefaultJunitRunConfiguration(rootProject)
files.forEach { it.write() }
}
private fun unpill(project: Project) {
initEnvironment(project)
removeExistingIdeaLibrariesAndModules()
removeJpsAndPillRunConfigurations()
removeAllArtifactConfigurations()
}
private fun removeExistingIdeaLibrariesAndModules() {
File(projectDir, ".idea/libraries").deleteRecursively()
File(projectDir, ".idea/modules").deleteRecursively()
}
private fun removeJpsAndPillRunConfigurations() {
File(projectDir, ".idea/runConfigurations")
.walk()
.filter { (it.name.startsWith("JPS_") || it.name.startsWith("Pill_")) && it.extension.toLowerCase() == "xml" }
.forEach { it.delete() }
}
private fun removeAllArtifactConfigurations() {
File(projectDir, ".idea/artifacts")
.walk()
.filter { it.extension.toLowerCase() == "xml" }
.forEach { it.delete() }
}
private fun copyRunConfigurations() {
val runConfigurationsDir = File(projectDir, "buildSrc/src/main/resources/runConfigurations")
val targetDir = File(projectDir, ".idea/runConfigurations")
val platformDirProjectRelative = "\$PROJECT_DIR\$/" + platformDir.toRelativeString(projectDir)
val additionalIdeaArgs = if (isAndroidStudioPlatform) "-Didea.platform.prefix=AndroidStudio" else ""
targetDir.mkdirs()
fun substitute(text: String): String {
return text
.replace("\$IDEA_HOME_PATH\$", platformDirProjectRelative)
.replace("\$ADDITIONAL_IDEA_ARGS\$", additionalIdeaArgs)
}
runConfigurationsDir.listFiles()
.filter { it.extension == "xml" }
.map { it.name to substitute(it.readText()) }
.forEach { File(targetDir, it.first).writeText(it.second) }
}
/*
This sets a proper (project root) working directory and a "idea.home.path" property to the default JUnit configuration,
so one does not need to make these changes manually.
*/
private fun setOptionsForDefaultJunitRunConfiguration(project: Project) {
val workspaceFile = File(projectDir, ".idea/workspace.xml")
if (!workspaceFile.exists()) {
project.logger.warn("${workspaceFile.name} does not exist, JUnit default run configuration was not modified")
return
}
val document = SAXBuilder().build(workspaceFile)
val rootElement = document.rootElement
fun Element.getOrCreateChild(name: String, vararg attributes: Pair<String, String>): Element {
for (child in getChildren(name)) {
if (attributes.all { (attribute, value) -> child.getAttributeValue(attribute) == value }) {
return child
}
}
return Element(name).apply {
for ((attributeName, value) in attributes) {
setAttribute(attributeName, value)
}
this@getOrCreateChild.addContent(this@apply)
}
}
val platformDirProjectRelative = "\$PROJECT_DIR\$/" + platformDir.toRelativeString(projectDir)
val runManagerComponent = rootElement.getOrCreateChild("component", "name" to "RunManager")
val junitConfiguration = runManagerComponent.getOrCreateChild(
"configuration",
"default" to "true",
"type" to "JUnit",
"factoryName" to "JUnit"
)
junitConfiguration.apply {
getOrCreateChild("option", "name" to "WORKING_DIRECTORY").setAttribute("value", "file://\$PROJECT_DIR\$")
getOrCreateChild("option", "name" to "VM_PARAMETERS").also { vmParams ->
var options = vmParams.getAttributeValue("value", "")
.split(' ')
.map { it.trim() }
.filter { it.isNotEmpty() }
fun addOrReplaceOptionValue(name: String, value: Any?) {
val optionsWithoutNewValue = options.filter { !it.startsWith("-D$name=") }
options = if (value == null) optionsWithoutNewValue else (optionsWithoutNewValue + listOf("-D$name=$value"))
}
val robolectricClasspath = project.rootProject
.project(":plugins:android-extensions-compiler")
.configurations.getByName("robolectricClasspath")
.files.joinToString(File.pathSeparator)
if (options.none { it == "-ea" }) {
options += "-ea"
}
addOrReplaceOptionValue("idea.home.path", platformDirProjectRelative)
addOrReplaceOptionValue("ideaSdk.androidPlugin.path", platformDirProjectRelative + "/plugins/android/lib")
addOrReplaceOptionValue("robolectric.classpath", robolectricClasspath)
addOrReplaceOptionValue("use.jps", "true")
addOrReplaceOptionValue("kotlinVersion", project.rootProject.extra["kotlinVersion"].toString())
val isAndroidStudioBunch = project.findProperty("versions.androidStudioRelease") != null
addOrReplaceOptionValue("idea.platform.prefix", if (isAndroidStudioBunch) "AndroidStudio" else null)
val androidJarPath = project.configurations.findByName("androidJar")?.singleFile
val androidSdkPath = project.configurations.findByName("androidSdk")?.singleFile
if (androidJarPath != null && androidSdkPath != null) {
addOrReplaceOptionValue("android.sdk", "\$PROJECT_DIR\$/" + androidSdkPath.toRelativeString(projectDir))
addOrReplaceOptionValue("android.jar", "\$PROJECT_DIR\$/" + androidJarPath.toRelativeString(projectDir))
}
vmParams.setAttribute("value", options.joinToString(" "))
}
}
val output = XMLOutputter().also {
it.format = Format.getPrettyFormat().apply {
setEscapeStrategy { Verifier.isHighSurrogate(it) || it == '"' }
setIndent(" ")
setTextMode(Format.TextMode.TRIM)
setOmitEncoding(false)
setOmitDeclaration(false)
}
}
val postProcessedXml = output.outputString(document)
.replace("&#x22;", "&quot;")
.replace("&#xA;", "&#10;")
.replace("&#xC;", "&#13;")
workspaceFile.writeText(postProcessedXml)
}
private fun attachPlatformSources(library: PLibrary): PLibrary {
val platformSourcesJar = File(platformDir, "../../../sources/intellij-$platformVersion-sources.jar")
if (library.classes.any { it.startsWith(platformDir) }) {
return library.attachSource(platformSourcesJar)
}
return library
}
private fun attachAsmSources(library: PLibrary): PLibrary {
val asmSourcesJar = File(platformDir, "../asm-shaded-sources/asm-src-$platformBaseNumber.jar")
val asmAllJar = File(platformDir, "lib/asm-all.jar")
if (library.classes.any { it == asmAllJar }) {
return library.attachSource(asmSourcesJar)
}
return library
}
private fun PProject.mapLibraries(vararg mappers: (PLibrary) -> PLibrary): PProject {
fun mapLibrary(root: POrderRoot): POrderRoot {
val dependency = root.dependency
if (dependency is PDependency.ModuleLibrary) {
val newLibrary = mappers.fold(dependency.library) { lib, mapper -> mapper(lib) }
return root.copy(dependency = dependency.copy(library = newLibrary))
}
return root
}
val modules = this.modules.map { it.copy(orderRoots = it.orderRoots.map(::mapLibrary)) }
return this.copy(modules = modules)
}
}

View File

@@ -0,0 +1,200 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
class PFile(val path: File, val text: String) {
fun write() {
path.parentFile.mkdirs()
path.writeText(text)
}
}
fun PFile(path: File, xml: xml) = PFile(path, xml.toString())
fun render(project: PProject): List<PFile> {
val files = mutableListOf<PFile>()
files += renderModulesFile(project)
project.modules.forEach { files += renderModule(project, it) }
project.libraries.forEach { files += renderLibrary(project, it) }
return files
}
private fun renderModulesFile(project: PProject) = PFile(
File(project.rootDirectory, ".idea/modules.xml"),
xml("project", "version" to 4) {
xml("component", "name" to "ProjectModuleManager") {
xml("modules") {
val pathContext = ProjectContext(project)
for (module in project.modules) {
val moduleFilePath = pathContext(module.moduleFile)
xml("module", "fileurl" to "file://$moduleFilePath", "filepath" to moduleFilePath)
}
}
}
}
)
private fun renderModule(project: PProject, module: PModule) = PFile(
module.moduleFile,
xml("module",
"type" to "JAVA_MODULE",
"version" to 4
) {
val moduleForProductionSources = module.moduleForProductionSources
if (moduleForProductionSources != null) {
xml("component", "name" to "TestModuleProperties", "production-module" to moduleForProductionSources.name)
}
val kotlinCompileOptionsList = module.contentRoots.flatMap { it.sourceRoots }.mapNotNull { it.kotlinOptions }
var kotlinCompileOptions = kotlinCompileOptionsList.firstOrNull()
for (otherOptions in kotlinCompileOptionsList.drop(1)) {
kotlinCompileOptions = kotlinCompileOptions?.intersect(otherOptions)
}
val pathContext = ModuleContext(project, module)
val platformVersion = (kotlinCompileOptions?.jvmTarget ?: "1.8")
val classesDirectory = File(project.rootDirectory, "out/production/${module.name}")
if (kotlinCompileOptions != null) {
xml("component", "name" to "FacetManager") {
xml("facet", "type" to "kotlin-language", "name" to "Kotlin") {
xml("configuration", "version" to 3, "platform" to "JVM $platformVersion", "useProjectSettings" to "false") {
xml("compilerSettings") {
xml(
"option",
"name" to "additionalArguments",
"value" to kotlinCompileOptions.extraArguments.joinToString(" ")
)
}
xml("compilerArguments") {
xml("option", "name" to "destination", "value" to pathContext(classesDirectory))
fun Any?.option(name: String) {
if (this != null) xml("option", "name" to name, "value" to this.toString())
}
kotlinCompileOptions.noStdlib.option("noStdlib")
kotlinCompileOptions.noReflect.option("noReflect")
module.name.option("moduleName")
xml("option", "name" to "jvmTarget", "value" to platformVersion)
kotlinCompileOptions.languageVersion.option("languageVersion")
kotlinCompileOptions.apiVersion.option("apiVersion")
xml("option", "name" to "pluginOptions") { xml("array") }
xml("option", "name" to "pluginClasspaths") { xml("array") }
}
}
}
}
}
xml("component",
"name" to "NewModuleRootManager",
"LANGUAGE_LEVEL" to "JDK_${platformVersion.replace('.', '_')}",
"inherit-compiler-output" to "true"
) {
xml("exclude-output")
for (contentRoot in module.contentRoots) {
xml("content", pathContext.url(contentRoot.path)) {
for (sourceRoot in contentRoot.sourceRoots) {
var args = arrayOf(pathContext.url(sourceRoot.path))
args += when (sourceRoot.kind) {
PSourceRoot.Kind.PRODUCTION -> ("isTestSource" to "false")
PSourceRoot.Kind.TEST -> ("isTestSource" to "true")
PSourceRoot.Kind.RESOURCES -> ("type" to "java-resource")
PSourceRoot.Kind.TEST_RESOURCES -> ("type" to "java-test-resource")
}
xml("sourceFolder", *args)
}
for (excludedDir in contentRoot.excludedDirectories) {
xml("excludeFolder", pathContext.url(excludedDir))
}
}
}
xml("orderEntry", "type" to "inheritedJdk")
xml("orderEntry", "type" to "sourceFolder", "forTests" to "false")
for (orderRoot in module.orderRoots) {
val dependency = orderRoot.dependency
val args = when (dependency) {
is PDependency.ModuleLibrary -> mutableListOf(
"type" to "module-library"
)
is PDependency.Module -> mutableListOf(
"type" to "module",
"module-name" to dependency.name
)
is PDependency.Library -> mutableListOf(
"type" to "library",
"name" to dependency.name,
"level" to "project"
)
}
if (orderRoot.scope != POrderRoot.Scope.COMPILE) {
args.add(1, "scope" to orderRoot.scope.toString())
}
if (dependency is PDependency.Module && orderRoot.isProductionOnTestDependency) {
args += ("production-on-test" to "")
}
if (orderRoot.isExported) {
args += ("exported" to "")
}
xml("orderEntry", *args.toTypedArray()) {
if (dependency is PDependency.ModuleLibrary) {
add(renderLibraryToXml(dependency.library, pathContext, named = false))
}
}
}
}
}
)
private fun renderLibrary(project: PProject, library: PLibrary): PFile {
val pathContext = ProjectContext(project)
// TODO find how IDEA escapes library names
val escapedName = library.renderName().replace(" ", "_").replace(".", "_").replace("-", "_")
return PFile(
File(project.rootDirectory, ".idea/libraries/$escapedName.xml"),
xml("component", "name" to "libraryTable") {
add(renderLibraryToXml(library, pathContext))
})
}
private fun renderLibraryToXml(library: PLibrary, pathContext: PathContext, named: Boolean = true): xml {
val args = if (named) arrayOf("name" to library.renderName()) else emptyArray()
return xml("library", *args) {
xml("CLASSES") {
library.classes.forEach { xml("root", pathContext.url(it)) }
}
xml("JAVADOC") {
library.javadoc.forEach { xml("root", pathContext.url(it)) }
}
xml("SOURCES") {
library.sources.forEach { xml("root", pathContext.url(it)) }
}
}
}
fun PLibrary.renderName() = name.takeIf { it != "unspecified" } ?: classes.first().nameWithoutExtension

View File

@@ -0,0 +1,61 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import shadow.org.jdom2.Document
import shadow.org.jdom2.Element
import shadow.org.jdom2.output.Format
import shadow.org.jdom2.output.XMLOutputter
class xml(val name: String, private vararg val args: Pair<String, Any>, block: xml.() -> Unit = {}) {
private companion object {
fun makeXml(name: String, vararg args: Pair<String, Any>, block: xml.() -> Unit = {}): xml {
return xml(name, *args, block = block)
}
}
private val children = mutableListOf<xml>()
private var value: Any? = null
init {
@Suppress("UNUSED_EXPRESSION")
block()
}
fun xml(name: String, vararg args: Pair<String, Any>, block: xml.() -> Unit = {}) {
children += makeXml(name, *args, block = block)
}
fun add(xml: xml) {
children += xml
}
fun raw(text: String) {
value = text
}
private fun toElement(): Element {
val element = Element(name)
for (arg in args) {
element.setAttribute(arg.first, arg.second.toString())
}
require(value == null || children.isEmpty())
value?.let { value ->
element.addContent(value.toString())
}
for (child in children) {
element.addContent(child.toElement())
}
return element
}
override fun toString(): String {
val document = Document().also { it.rootElement = toElement() }
val output = XMLOutputter().also { it.format = Format.getPrettyFormat() }
return output.outputString(document)
}
}

View File

@@ -5,12 +5,10 @@
import com.jakewharton.dex.*
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.tasks.*
import org.gradle.jvm.tasks.Jar
import java.io.File
@CacheableTask
open class DexMethodCount : DefaultTask() {
data class Counts(
@@ -21,23 +19,34 @@ open class DexMethodCount : DefaultTask() {
val byClass: Map<String, Int>
)
@Classpath
init {
outputs.upToDateWhen { !shouldPrintTeamCityStatistics } // always execute when teamCityStatistics output is required
}
@InputFile
lateinit var jarFile: File
@Optional
@Input
@Optional
var ownPackages: List<String>? = null
@Internal
// ##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='62362']
@Input
@Optional
var teamCityStatistics: Boolean? = null
private val shouldPrintTeamCityStatistics = teamCityStatistics ?: project.hasProperty("teamcity")
@Input
@Optional
var artifactName: String? = null
@get:Input
val artifactOrArchiveName: String
get() = artifactName ?: project.name
private val artifactOrArchiveName get() = artifactName ?: project.name
fun from(jar: Jar) {
jarFile = jar.archiveFile.get().asFile
artifactName = jar.archiveBaseName.orNull
jarFile = jar.archivePath
artifactName = jar.baseName
dependsOn(jar)
}
@@ -45,13 +54,16 @@ open class DexMethodCount : DefaultTask() {
lateinit var counts: Counts
@get:OutputFile
val detailOutputFile: File
get() = project.buildDir.resolve("$artifactOrArchiveName-method-count.txt")
val detailOutputFile: File get() = project.buildDir.resolve("$artifactOrArchiveName-method-count.txt")
@TaskAction
fun invoke() {
val methods = dexMethods(jarFile)
val counts = methods.getCounts().also { this.counts = it }
printTotals(counts)
printTCStats(counts)
outputDetails(counts)
}
@@ -59,7 +71,7 @@ open class DexMethodCount : DefaultTask() {
val byPackage = this.groupingBy { it.`package` }.eachCount()
val byClass = this.groupingBy { it.declaringType }.eachCount()
val ownPackages = ownPackages?.map { "$it." }
val ownPackages = ownPackages?.map { it + '.' }
val byOwnPackages = if (ownPackages != null) {
this.partition { method -> ownPackages.any { method.declaringType.startsWith(it) } }.let {
it.first.size to it.second.size
@@ -75,6 +87,26 @@ open class DexMethodCount : DefaultTask() {
)
}
private fun printTotals(counts: Counts) {
logger.lifecycle("Artifact $artifactOrArchiveName, total methods: ${counts.total}")
ownPackages?.let { packages ->
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from packages ${packages.joinToString { "$it.*" }}: ${counts.totalOwnPackages}")
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from other packages: ${counts.totalOtherPackages}")
}
}
private fun printTCStats(counts: Counts) {
if (shouldPrintTeamCityStatistics) {
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='${counts.total}']")
counts.totalOwnPackages?.let { value ->
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OwnPackages' value='$value']")
}
counts.totalOtherPackages?.let { value ->
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OtherPackages' value='$value']")
}
}
}
private fun outputDetails(counts: Counts) {
detailOutputFile.printWriter().use { writer ->
writer.println("${counts.total.padRight()}\tTotal methods")
@@ -94,67 +126,9 @@ open class DexMethodCount : DefaultTask() {
}
}
}
}
open class DexMethodCountStats : DefaultTask() {
@Internal
lateinit var from: TaskProvider<DexMethodCount>
@get:InputFile
internal val inputFile
get() = from.get().detailOutputFile
@TaskAction
private fun printStats() {
val artifactOrArchiveName = from.get().artifactOrArchiveName
inputFile.reader().useLines { lines ->
fun String.getStatValue() = substringBefore("\t").trim()
val ownPackages = from.get().ownPackages
val statsLineCount = if (ownPackages == null) 1 else 3
val stats = lines.take(statsLineCount).map { it.getStatValue() }.toList()
val total = stats[0]
logger.lifecycle("Artifact $artifactOrArchiveName, total methods: $total")
if (project.kotlinBuildProperties.isTeamcityBuild) {
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='$total']")
}
ownPackages?.let { packages ->
val totalOwnPackages = stats[1]
val totalOtherPackages = stats[2]
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from packages ${packages.joinToString { "$it.*" }}: $totalOwnPackages")
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from other packages: $totalOtherPackages")
if (project.kotlinBuildProperties.isTeamcityBuild) {
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OwnPackages' value='$totalOwnPackages']")
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OtherPackages' value='$totalOtherPackages']")
}
}
}
}
}
fun Project.printStats(dexMethodCount: TaskProvider<DexMethodCount>) {
val dexMethodCountStats = tasks.register("dexMethodCountStats", DexMethodCountStats::class.java) {
dependsOn(dexMethodCount)
from = dexMethodCount
}
dexMethodCount.configure {
finalizedBy(dexMethodCountStats)
}
}
fun Project.dexMethodCount(action: DexMethodCount.() -> Unit): TaskProvider<DexMethodCount> {
val dexMethodCount = tasks.register("dexMethodCount", DexMethodCount::class.java, action)
printStats(dexMethodCount)
tasks.getByName("check").dependsOn(dexMethodCount)
return dexMethodCount
}
private val DexMethod.`package`: String get() = declaringType.substringBeforeLast('.')
private fun Int.padRight() = toString().padStart(5, ' ')

View File

@@ -4,10 +4,9 @@ import org.codehaus.groovy.runtime.InvokerHelper
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer
import org.gradle.api.artifacts.maven.MavenDeployment
import org.gradle.api.artifacts.maven.MavenResolver
import org.gradle.api.plugins.MavenPluginConvention
import org.gradle.api.plugins.MavenRepositoryHandlerConvention
import org.gradle.api.publication.maven.internal.deployer.MavenRemoteRepository
import org.gradle.api.tasks.Upload
@@ -31,12 +30,6 @@ open class PublishedKotlinModule : Plugin<Project> {
plugins.apply("maven")
val publishedRuntime by configurations.creating {
the<MavenPluginConvention>()
.conf2ScopeMappings
.addMapping(0, this, Conf2ScopeMappingContainer.RUNTIME)
}
if (!project.hasProperty("prebuiltJar")) {
plugins.apply("signing")
@@ -48,7 +41,7 @@ open class PublishedKotlinModule : Plugin<Project> {
sign(configurations["archives"])
}
tasks.named<Sign>("signArchives").configure {
(tasks.getByName("signArchives") as Sign).apply {
enabled = signingRequired
}
}
@@ -105,9 +98,9 @@ open class PublishedKotlinModule : Plugin<Project> {
}
}
tasks.named<Upload>("uploadArchives").configure {
val preparePublication = project.rootProject.tasks.getByName("preparePublication")
val preparePublication = project.rootProject.tasks.named("preparePublication").get()
val uploadArchives = (tasks.getByName("uploadArchives") as Upload).apply {
dependsOn(preparePublication)
@@ -159,8 +152,8 @@ open class PublishedKotlinModule : Plugin<Project> {
}
}
tasks.register("publish") {
dependsOn(tasks.named("uploadArchives"))
tasks.create("publish") {
dependsOn(uploadArchives)
}
}
}

View File

@@ -1,25 +0,0 @@
import org.gradle.api.Action
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.NamedDomainObjectProvider
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
val NamedDomainObjectContainer<Configuration>.publishedRuntime: NamedDomainObjectProvider<Configuration> get() = named("publishedRuntime")
fun DependencyHandler.publishedRuntime(dependencyNotation: Any): Dependency? =
add("publishedRuntime", dependencyNotation)
fun DependencyHandler.publishedRuntime(
dependencyNotation: String,
dependencyConfiguration: Action<ExternalModuleDependency>
): ExternalModuleDependency =
addDependencyTo(this, "publishedRuntime", dependencyNotation, dependencyConfiguration)

View File

@@ -1,5 +1,4 @@
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
@@ -38,13 +37,7 @@ val Project.sourceSets: SourceSetContainer
get() = javaPluginConvention().sourceSets
val Project.mainSourceSet: SourceSet
get() = javaPluginConvention().mainSourceSet
val Project.testSourceSet: SourceSet
get() = javaPluginConvention().testSourceSet
val JavaPluginConvention.mainSourceSet: SourceSet
get() = sourceSets.getByName("main")
val JavaPluginConvention.testSourceSet: SourceSet
val Project.testSourceSet: SourceSet
get() = sourceSets.getByName("test")

View File

@@ -5,17 +5,14 @@ import org.jetbrains.org.objectweb.asm.*
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.*
import java.util.jar.JarFile
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
private val CONSTANT_TIME_FOR_ZIP_ENTRIES = GregorianCalendar(1980, 1, 1, 0, 0, 0).timeInMillis
/**
* Removes @kotlin.Metadata annotations from compiled Kotlin classes
*/
fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFile: File, preserveFileTimestamps: Boolean = true) {
fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFile: File) {
val classRegex = classNamePattern.toRegex()
assert(inFile.exists()) { "Input file not found at $inFile" }
@@ -52,9 +49,6 @@ fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFil
}
val newEntry = ZipEntry(entry.name)
if (!preserveFileTimestamps) {
newEntry.time = CONSTANT_TIME_FOR_ZIP_ENTRIES
}
outJar.putNextEntry(newEntry)
outJar.write(outBytes)
outJar.closeEntry()

View File

@@ -21,24 +21,19 @@
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.project
import org.gradle.kotlin.dsl.task
import java.io.File
import java.lang.Character.isLowerCase
import java.lang.Character.isUpperCase
import java.nio.file.Files
import java.nio.file.Path
fun Project.projectTest(
taskName: String = "test",
parallel: Boolean = false,
shortenTempRootName: Boolean = false,
body: Test.() -> Unit = {}
): TaskProvider<Test> = getOrCreateTask(taskName) {
fun Project.projectTest(taskName: String = "test", parallel: Boolean = false, body: Test.() -> Unit = {}): Test = getOrCreateTask(taskName) {
doFirst {
val commandLineIncludePatterns = (filter as? DefaultTestFilter)?.commandLineIncludePatterns ?: mutableSetOf()
val commandLineIncludePatterns = (filter as? DefaultTestFilter)?.commandLineIncludePatterns ?: emptySet()
val patterns = filter.includePatterns + commandLineIncludePatterns
if (patterns.isEmpty() || patterns.any { '*' in it }) return@doFirst
patterns.forEach { pattern ->
@@ -92,6 +87,7 @@ fun Project.projectTest(
jvmArgs(
"-ea",
"-XX:+HeapDumpOnOutOfMemoryError",
"-Xmx1600m",
"-XX:+UseCodeCacheFlushing",
"-XX:ReservedCodeCacheSize=128m",
"-Djna.nosys=true"
@@ -100,7 +96,6 @@ fun Project.projectTest(
maxHeapSize = "1600m"
systemProperty("idea.is.unit.test", "true")
systemProperty("idea.home.path", intellijRootDir().canonicalPath)
systemProperty("java.awt.headless", "true")
environment("NO_FS_ROOTS_ACCESS_CHECK", "true")
environment("PROJECT_CLASSES_DIRS", testSourceSet.output.classesDirs.asPath)
environment("PROJECT_BUILD_DIR", buildDir)
@@ -116,8 +111,7 @@ fun Project.projectTest(
(teamcity?.get("teamcity.build.tempDir") as? String)
?: System.getProperty("java.io.tmpdir")
systemTempRoot.let {
val prefix = (project.name + "Project_" + taskName + "_").takeUnless { shortenTempRootName }
subProjectTempRoot = Files.createTempDirectory(File(systemTempRoot).toPath(), prefix)
subProjectTempRoot = Files.createTempDirectory(File(systemTempRoot).toPath(), project.name + "Project_" + taskName + "_")
systemProperty("java.io.tmpdir", subProjectTempRoot.toString())
}
}
@@ -135,16 +129,15 @@ fun Project.projectTest(
if (parallel) {
maxParallelForks =
project.findProperty("kotlin.test.maxParallelForks")?.toString()?.toInt()
?: Math.max(Runtime.getRuntime().availableProcessors() / if (kotlinBuildProperties.isTeamcityBuild) 2 else 4, 1)
?: Math.max(Runtime.getRuntime().availableProcessors() / 2, 1)
}
body()
}
private inline fun String.isFirstChar(f: (Char) -> Boolean) = isNotEmpty() && f(first())
inline fun <reified T : Task> Project.getOrCreateTask(taskName: String, noinline body: T.() -> Unit): TaskProvider<T> =
if (tasks.names.contains(taskName)) tasks.named(taskName, T::class.java).apply { configure(body) }
else tasks.register(taskName, T::class.java, body)
inline fun <reified T : Task> Project.getOrCreateTask(taskName: String, body: T.() -> Unit): T =
(tasks.findByName(taskName)?.let { it as T } ?: task<T>(taskName)).apply { body() }
object TaskUtils {
fun useAndroidSdk(task: Task) {

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