Compare commits

...

104 Commits

Author SHA1 Message Date
Ilya Chernikov
4773d54bb7 Put native-platform-uberjar.jar into compiler embeddable and remove dependency from the compiler runner 2016-12-21 09:47:57 +01:00
Ilya Chernikov
904f5ac0bc Update changelog 2016-12-20 18:38:14 +01:00
Alexey Tsvetkov
f6c82f34fc Remove reference to removed dependency from pom.xml 2016-12-20 20:25:41 +03:00
Alexey Tsvetkov
264409c399 Fix getting daemon connection in JPS 2016-12-20 14:47:08 +03:00
Ilya Gorbunov
407a39c46f Add SinceKotlin to new coerceIn method.
(cherry picked from commit 2209631)
2016-12-20 14:06:50 +03:00
Ilya Gorbunov
7da0e66fdc Rename ClosedComparableRange to ClosedFloatingPointRange
(cherry picked from commit 10f8e70)
2016-12-20 14:06:42 +03:00
Ilya Gorbunov
b7cec10de4 Do not deploy examples as artifacts to maven
(cherry picked from commit 5ee6170)
2016-12-20 14:06:04 +03:00
Ilya Chernikov
378a11c898 Fix TC compilation and kapt3 tests compilation
(cherry picked from commit 4f2410f)
2016-12-20 10:56:26 +01:00
Mikhael Bogdanov
46fb174831 Adedd quickfix check if @PublishedApi stub already exists
(cherry picked from commit 5222768)
2016-12-20 09:47:18 +01:00
Mikhael Bogdanov
83689dff92 Support properties in @PublishedApi bridge quickfix
(cherry picked from commit c38b556)
2016-12-20 09:47:16 +01:00
Mikhael Bogdanov
aa7d69a81a Published-api checker refactoring, support java package-protected visibility
(cherry picked from commit 6ca1d47)
2016-12-20 09:47:13 +01:00
Ilya Gorbunov
a9d54a52a9 Fix some API holes in headers 2016-12-20 11:30:58 +03:00
Alexey Tsvetkov
d72c1cda8e Minor: remove default value of retryOnConnectionError parameter 2016-12-19 23:38:58 +03:00
Alexey Tsvetkov
183f135505 Minor: replace map().flatten()->flatMap() 2016-12-19 23:38:58 +03:00
Alexey Tsvetkov
df9cd57d24 Minor: rename enableIC->withIC 2016-12-19 23:38:57 +03:00
Alexey Tsvetkov
c54f2b2966 Minor: fix snapshot version used in kapt test kt15001 2016-12-19 23:38:57 +03:00
Alexey Tsvetkov
212ff73488 Run kapt with daemon 2016-12-19 23:38:56 +03:00
Alexey Tsvetkov
2dc623a2c9 Report messages from kapt using MessageCollector
This allows to print messages when daemon is used.
System out is not copied to daemon client,
because multiple compilations can occur in parallel.
2016-12-19 23:38:56 +03:00
Alexey Tsvetkov
7cbc385193 Optimize searching for compiler jar 2016-12-19 23:38:55 +03:00
Alexey Tsvetkov
f62d7a9593 Unify Gradle and Kotlin daemon cache version checking 2016-12-19 23:38:55 +03:00
Alexey Tsvetkov
5a04cbe94a Clear jar cache with daemon 2016-12-19 23:38:54 +03:00
Alexey Tsvetkov
5968e9e8c9 Compile multiplatform projects with daemon 2016-12-19 23:38:54 +03:00
Alexey Tsvetkov
cccd5e8d22 Minor: add missing import 2016-12-19 23:38:53 +03:00
Alexey Tsvetkov
2cb590df7f Fix gradle subplugin example 2016-12-19 23:38:53 +03:00
Alexey Tsvetkov
db293c8d10 Fix multiproject Gradle IC with daemon 2016-12-19 23:38:52 +03:00
Alexey Tsvetkov
7a6bce696e Set property "idea.plugins.compatible.build" every time production environment is created
Gradle can wipe system properties between the build.
If this property is not set, "idea.properties is not found exception"
can be thrown when creating KotlinCoreEnvironment.
2016-12-19 23:38:52 +03:00
Alexey Tsvetkov
098c0662ca Implement server side IC 2016-12-19 23:38:51 +03:00
Alexey Tsvetkov
8d97034f1e Refactoring: extract withDaemon 2016-12-19 23:38:51 +03:00
Alexey Tsvetkov
4f2835481c Refactoring: pass MessageCollector, OutputItemsCollector in CompilerEnvironment 2016-12-19 23:38:50 +03:00
Alexey Tsvetkov
44980733b8 Minor: move GradleCompilerEnvironment to separate file 2016-12-19 23:38:50 +03:00
Alexey Tsvetkov
541e389371 Minor: remove redundant call 2016-12-19 23:38:49 +03:00
Alexey Tsvetkov
9ebefb2416 Move IC tests to compiler
Fixing IC after moving it from Gradle to the compiler in commit fdd86c246d
2016-12-19 23:38:39 +03:00
Alexey Tsvetkov
ef40daaaa0 Move file utils
Fixing IC after moving it from Gradle to the compiler in commit fdd86c246d
2016-12-19 23:38:30 +03:00
Alexey Tsvetkov
be0ceaa17b Make IC classes public
Fixing IC after moving it from Gradle to the compiler in commit fdd86c246d
2016-12-19 23:38:21 +03:00
Alexey Tsvetkov
4488f8b558 Remove remaining gradle api references
Fixing IC after moving it from Gradle to the compiler in commit fdd86c246d
2016-12-19 23:38:11 +03:00
Alexey Tsvetkov
1e0a275974 Replace org.jetbrains.kotlin.com.intellij with com.intellij
Fixing IC after moving it from Gradle to the compiler in commit fdd86c246d
2016-12-19 23:37:55 +03:00
Alexey Tsvetkov
fdd86c246d Move IC from Gradle to compiler
Reasons for moving:
1. Integration with Kotlin daemon for Gradle.
Gradle bundles Kotlin compiler (kotlin-compiler-embeddable) since Gradle 3.2.
There is no plugin isolation in Gradle, so strange compilation errors/exceptions may happen.
We decided to fix this problem by compiling out-of-process using Kotlin daemon.

Reasons for moving IC to the compiler:
* Better isolation from Gradle process.
* Incremental compilation logic is not scattered across two process and multiple modules.
* Makes it possible to implement standalone CLI IC
2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
7a8e140908 Replace Gradle logger with ICReporter 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
7793d3fa10 Refactoring: extract interface AnnotationFileUpdater 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
9b8a45f754 Rename: IncReporter->ICReporter 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
876d540512 Remove source annotations removing (not needed with KAPT3) 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
a13a307cb4 Minor: log compiler arguments 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
388fe0d353 Use daemon when compiling Kotlin to JS 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
360ec3ca25 Use ProcessLauncher from native platform for out-of-process compilation 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
2250038c67 Add a way to customize compiler file in build.gradle 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
cb089b31c8 Implement fallback strategies 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
e955124019 Run compiler via Kotlin daemon in Gradle plugin 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
9bb390e208 Refactoring: extract JPS specific code from compiler-runner 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
7be97bb4b0 Add compiler daemon client and runner to maven build 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
b6f0128153 Minor: remove ImmutableMapBuilder reference from CompilerOutputParser 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
2dc3262295 Convert CompilerOutputParser: convert to kotlin 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
2a6fc323d3 Convert CompilerOutputParser: rename file 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
87b151e94a Introduce compiler-runner module 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
4bfaa638b3 Convert CompilerEnvironment to Kotlin: actual conversion 2016-12-19 23:36:30 +03:00
Alexey Tsvetkov
61c697e938 Convert CompilerEnvironment to Kotlin: rename file 2016-12-19 23:36:30 +03:00
Alexander Udalov
8b310ce329 Disable runtime versions consistency checker temporarily
It should be enabled back as soon as Kotlin-Version attribute is written to
manifests of runtime jars in the Maven build

(cherry picked from commit f57bbeed58)
2016-12-19 22:34:27 +03:00
Alexander Udalov
0834a32151 Update tests on header/impl
- add test on enum entry calling a constructor
- add test on deep nesting of header/impl classes
- move test on resolving nested class via impl typealias to integration test,
  it's an unsupported case at the moment
2016-12-19 22:34:26 +03:00
Alexander Udalov
ee75a95912 Minor, remove unnecessary test data
These cases are already tested in diagnostic tests
2016-12-19 22:34:25 +03:00
Stanislav Erokhin
ec292c6cf9 Discriminate header classes in member scope.
We made it because of non-stable name resolution when project is multi platform. For such projects in platform module we have two classifiers with the same name, but impl class or type alias should win!
2016-12-19 22:34:24 +03:00
Alexander Udalov
ed29a60a8c Support header/impl enum classes
- prohibit constructors for header enum classes
- prohibit bodies for header enum entries
- all entries from header enum must be present in impl enum
2016-12-19 22:34:23 +03:00
Alexander Udalov
d9401c4d71 Support nested header/impl classes 2016-12-19 22:34:19 +03:00
Alexander Udalov
a54127558f Relax requirements on function modifiers in multiplatform projects
Allow to implement header functions with external/tailrec/inline/infix/operator
functions
2016-12-19 22:32:23 +03:00
Alexander Udalov
6e592110fa Do not report errors on 'impl' declarations with -Xno-check-impl
Allow 'impl' modifier on a declaration even if it's not an implementation of
any header declaration
2016-12-19 22:32:22 +03:00
Alexander Udalov
3d53348ea9 Allow open impl class for final header class 2016-12-19 22:32:22 +03:00
Alexander Udalov
42b2c653cc Allow fake overrides and delegates to be impl for header declarations
Also fix a bug with matching supertype lists of header/impl classes
2016-12-19 22:32:21 +03:00
Alexander Udalov
a9ff441b67 Allow impl class to be data class, allow impl constructor properties 2016-12-19 22:32:20 +03:00
Alexander Udalov
d53bc2e358 Rename platform->header, definition->impl in test data 2016-12-19 22:32:19 +03:00
Dmitry Jemerov
61a650119b Don't show "Kotlin not configured" notification for projects that have Kotlin common runtime in scope
#KT-15331 Fixed

(cherry picked from commit 5f124e9)
2016-12-19 19:22:33 +01:00
Yan Zhulanow
25b11e3068 Kapt3: Set correct compiler options when the annotation processing classpath is empty (KT-15146). Disable annotation processing in Javac task a bit earlier 2016-12-19 21:15:27 +03:00
Yan Zhulanow
8ceae7f4c4 Allopen, Noarg: Support transitive meta-annotations 2016-12-19 21:02:45 +03:00
Yan Zhulanow
06015e2770 Allopen, minor: Add test for anonymous object 2016-12-19 21:02:07 +03:00
Dmitry Jemerov
f15d74c1e5 Index and locate .kotlin_metadata files in IDE
(cherry picked from commit bc22b67)
2016-12-19 17:43:16 +01:00
Alexey Sedunov
7aed4dfc1f Minor: Rename "Default" platform to "Common"
(cherry picked from commit a84275b)
2016-12-19 18:36:35 +03:00
Alexey Sedunov
6c6f1244c4 Multi-platform Projects: Enable multi-platform projects for platform modules which depend on common modules
(cherry picked from commit 332d1f6)
2016-12-19 18:35:11 +03:00
Alexey Sedunov
eea1b5fcc6 Kotlin Facet: Detect module platform using Gradle plugin id/stdlib
artifact id (Gradle import)
(cherry picked from commit df33455)
2016-12-19 18:35:03 +03:00
Alexey Sedunov
5af6db525a Kotlin Facet: Add "Use project settings" option
(cherry picked from commit eac0c9b)
2016-12-19 18:34:55 +03:00
Alexey Sedunov
d3efabdb58 Kotlin Facet: Do not serialize default values of facet configuration
(cherry picked from commit 4ed030d)
2016-12-19 18:34:46 +03:00
Mikhail Glukhikh
f41019e962 Build fix 2016-12-19 15:21:17 +03:00
Mikhail Glukhikh
9a7a2f842a Multi-platform navigation fix: from class to type alias & vice versa
(cherry picked from commit 39ca78f)
2016-12-19 15:13:18 +03:00
Mikhail Glukhikh
8e0708d891 MemberDescriptor ancestor extracted to ClassifierDescriptorWithTypeParameters
(cherry picked from commit b363d34)
2016-12-19 15:13:06 +03:00
Mikhail Glukhikh
7c5d8a85b9 Multi-platform fix: no more errors for top-level impl fun / val / var in IDE
(cherry picked from commit 5947d49)
2016-12-19 15:12:25 +03:00
Denis Zharkov
d5c17e0509 Support async iterator case with coroutines
Not all the `hasNext` operators return types is exactly Z,
suspend operators return boxed versions.

So the fix is just coercing result value after invoked function to Z
2016-12-19 11:11:35 +03:00
Denis Zharkov
4c061a93d4 Minor. Simplify suspension point processing
Move type coercing logic from transformer to ExpressionCodegen.

For suspension points it's always guaranteed that values
returned from suspension points are always can be successfully casted
to appropriate type, because they cannot return SUSPENDED marker
(it gets processed via CoroutineTransformerMethodVisitor).
2016-12-19 11:11:34 +03:00
Denis Zharkov
b3142784ff Refine returns codegen for suspend functions
This change should make the logic a bit more simple.
For all suspend functions/coroutines treat them in expression codegen
like they return boxed version of the original type.

Everything works fine then, except Unit type functions:
their bodies must be generated just like they're VOID and then load
Unit on stack manually.
2016-12-19 11:11:34 +03:00
Alexey Tsvetkov
6433145bad Fix references from test to main in Gradle JS plugin with default output file 2016-12-17 21:46:58 +03:00
Alexey Tsvetkov
5b7968beca Add references from test to main in multiplatform test project 2016-12-17 21:46:54 +03:00
Alexey Tsvetkov
5878d9e00f Avoid adding common sources to platform source set
If common sources are added to a platform source set,
then IDE sees common src dir as a source root in a platform project,
which is incorrect.
2016-12-17 21:46:50 +03:00
Alexey Tsvetkov
4b2b86b32e Fix mapping kotlin properties in JS plugin 2016-12-17 21:46:46 +03:00
Alexey Andreev
f6c7ba69cc JS: when translating content of js() function, rename all free references if they point to Kotlin local variable with the same name. See KT-15212 2016-12-17 12:23:22 +03:00
Denis Zharkov
6b2982a681 Rename RestrictsSuspendExtensions -> RestrictsSuspension 2016-12-16 18:57:11 +03:00
Dmitry Jemerov
17b3b6faf8 Migration for JS extension functions and properties marked with @native/external
#KT-15269 Fixed

(cherry picked from commit 63785b5)
2016-12-16 15:40:15 +01:00
Dmitry Jemerov
a9777fe706 Add 1.1 EAP repository when creating a new Gradle project with 1.1 EAP
#KT-15293 Fixed

(cherry picked from commit ace4407)
2016-12-16 15:40:04 +01:00
Alexander Udalov
9042e3a1af Fix kotlinFunction for inline reified methods in reflection
Inline functions with reified type parameters are generated as private (see
AsmUtil.specialCaseVisibility), so we should treat them as "declared" in
reflection to look them up via getDeclaredMethod, not getMethod

 #KT-14721 Fixed

(cherry picked from commit 49de52e7ef)
2016-12-16 16:28:52 +03:00
Alexander Udalov
4201c63466 Minor, move isInlineOnlyOrReified to module descriptors
(cherry picked from commit 3a0100f604)
2016-12-16 16:28:48 +03:00
Mikhael Bogdanov
790115d1cf Uast update due to new diagnostic for delegation by
(cherry picked from commit 0949f55)
2016-12-16 13:31:46 +01:00
Mikhael Bogdanov
815377d726 'SubpackagesImportingScope' class update due to new diagnostic
(cherry picked from commit 547704c)
2016-12-16 13:31:44 +01:00
Mikhael Bogdanov
c3629ddfad Report error when delegation method hides superttype override
#KT-12531 Fixed

(cherry picked from commit 761aa9d)
2016-12-16 13:31:41 +01:00
Mikhael Bogdanov
8e592706f6 Test data update
(cherry picked from commit 686b698)
2016-12-16 13:31:38 +01:00
Mikhael Bogdanov
0f52469dbc Fix for KT-14774: Incorrect inner class modifier generated for sealed inner classes
#KT-14774 Fixed

(cherry picked from commit 004ff86)
2016-12-16 13:31:29 +01:00
Denis Zharkov
374b64350a Add test on inference with SAM adapter
#KT-12144 Fixed
2016-12-16 15:06:59 +03:00
Nikolay Krasko
99160027d6 Invalidate Script class finder caches as soon script classpath caches are invalidated (KT-14538)
#KT-14538 Fixed

(cherry picked from commit 654cecd)
2016-12-16 14:20:12 +03:00
Nikolay Krasko
9b1c63e542 Run invalidating script caches when reindexing is ready (KT-14538)
Explanation why it leads to red code after new project opening

 1. No script files are found after project initialization.
 2. KotlinScriptDependenciesIndexableSetContributor triggers caching classpath via getAllScriptsClasspath(). Empty classpath is cached.
 3. KotlinScriptDependenciesClassFinder.calcClassRoots() always get empty classpath.

 #KT-14538 In Progress

(cherry picked from commit f7b60e6)
2016-12-16 14:20:03 +03:00
Nikolay Krasko
1c694012c2 Revert "Filter out first dependency from module dependencies"
This reverts commit 868495437c.

(cherry picked from commit 9759319)
2016-12-16 14:19:47 +03:00
Denis Zharkov
9d9f7d6315 Minor. Update tests on coroutines 2016-12-16 13:27:44 +03:00
426 changed files with 7695 additions and 3739 deletions

View File

@@ -25,6 +25,7 @@
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/native-platform-uberjar.jar" path-in-jar="/" />
<element id="module-output" name="android-extensions-jps" />
<element id="module-output" name="build-common" />
<element id="module-output" name="compiler-runner" />
</root>
</artifact>
</component>

2
.idea/modules.xml generated
View File

@@ -25,6 +25,7 @@
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli.iml" filepath="$PROJECT_DIR$/compiler/cli/cli.iml" group="compiler/cli" />
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli-common/cli-common.iml" filepath="$PROJECT_DIR$/compiler/cli/cli-common/cli-common.iml" group="compiler/cli" />
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli-runner/cli-runner.iml" filepath="$PROJECT_DIR$/compiler/cli/cli-runner/cli-runner.iml" group="compiler/cli" />
<module fileurl="file://$PROJECT_DIR$/compiler/compiler-runner/compiler-runner.iml" filepath="$PROJECT_DIR$/compiler/compiler-runner/compiler-runner.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/tests/compiler-tests.iml" filepath="$PROJECT_DIR$/compiler/tests/compiler-tests.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/tests-java8/compiler-tests-java8.iml" filepath="$PROJECT_DIR$/compiler/tests-java8/compiler-tests-java8.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" filepath="$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" group="compiler" />
@@ -55,6 +56,7 @@
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" group="ide" />
<module fileurl="file://$PROJECT_DIR$/idea-runner/idea-runner.iml" filepath="$PROJECT_DIR$/idea-runner/idea-runner.iml" group="ide" />
<module fileurl="file://$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" filepath="$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" group="ide" />
<module fileurl="file://$PROJECT_DIR$/compiler/incremental-compilation-impl/incremental-compilation-impl.iml" filepath="$PROJECT_DIR$/compiler/incremental-compilation-impl/incremental-compilation-impl.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" filepath="$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" group="compiler/cli" />
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.ir2cfg/ir.ir2cfg.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.ir2cfg/ir.ir2cfg.iml" group="compiler/ir" />
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" group="compiler/ir" />

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.cli.common.ExitCode
import java.io.File
abstract class IncReporter {
abstract class ICReporter {
abstract fun report(message: ()->String)
// used in Gradle plugin

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.TargetId

View File

@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
@@ -70,8 +69,7 @@ fun makeModuleFile(name: String, isTest: Boolean, outputDir: File, sourcesToComp
fun makeCompileServices(
incrementalCaches: Map<TargetId, IncrementalCache>,
lookupTracker: LookupTracker,
compilationCanceledStatus: CompilationCanceledStatus?,
sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler? = null
compilationCanceledStatus: CompilationCanceledStatus?
): Services =
with(Services.Builder()) {
register(IncrementalCompilationComponents::class.java,
@@ -79,9 +77,6 @@ fun makeCompileServices(
compilationCanceledStatus?.let {
register(CompilationCanceledStatus::class.java, it)
}
sourceRetentionAnnotationHandler?.let {
register(SourceRetentionAnnotationHandler::class.java, it)
}
build()
}
@@ -187,7 +182,7 @@ data class DirtyData(
fun <Target> CompilationResult.getDirtyData(
caches: Iterable<IncrementalCacheImpl<Target>>,
reporter: IncReporter
reporter: ICReporter
): DirtyData {
val dirtyLookupSymbols = HashSet<LookupSymbol>()
val dirtyClassesFqNames = HashSet<FqName>()
@@ -225,7 +220,7 @@ fun <Target> CompilationResult.getDirtyData(
fun mapLookupSymbolsToFiles(
lookupStorage: LookupStorage,
lookupSymbols: Iterable<LookupSymbol>,
reporter: IncReporter,
reporter: ICReporter,
excludes: Set<File> = emptySet()
): Set<File> {
val dirtyFiles = HashSet<File>()
@@ -242,7 +237,7 @@ fun mapLookupSymbolsToFiles(
fun <Target> mapClassesFqNamesToFiles(
caches: Iterable<IncrementalCacheImpl<Target>>,
classesFqNames: Iterable<FqName>,
reporter: IncReporter,
reporter: ICReporter,
excludes: Set<File> = emptySet()
): Set<File> {
val dirtyFiles = HashSet<File>()
@@ -260,8 +255,6 @@ fun <Target> mapClassesFqNamesToFiles(
return dirtyFiles
}
private fun File.isJavaFile() = extension.equals(JavaFileType.INSTANCE.defaultExtension, ignoreCase = true)
private fun findSrcDirRoot(file: File, roots: Iterable<File>): File? =
roots.firstOrNull { FileUtil.isAncestor(it, file, false) }

View File

@@ -16,15 +16,16 @@
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
import java.io.File
class SourceRetentionAnnotationHandlerImpl : SourceRetentionAnnotationHandler {
private val mutableSourceRetentionAnnotations = mutableSetOf<String>()
val sourceRetentionAnnotations: Set<String>
get() = mutableSourceRetentionAnnotations
override fun register(internalName: String) {
mutableSourceRetentionAnnotations += internalName
fun File.isJavaFile() =
extension.equals("java", ignoreCase = true)
fun File.isKotlinFile(): Boolean =
extension.let {
"kt".equals(it, ignoreCase = true) ||
"kts".equals(it, ignoreCase = true)
}
}
fun File.isClassFile(): Boolean =
extension.equals("class", ignoreCase = true)

View File

@@ -107,6 +107,8 @@
<include name="compiler/plugin-api/src"/>
<include name="compiler/daemon/src"/>
<include name="compiler/daemon/daemon-common/src"/>
<include name="build-common/src"/>
<include name="compiler/incremental-compilation-impl/src"/>
<include name="compiler/serialization/src"/>
<include name="compiler/util/src"/>
<include name="js/js.dart-ast/src"/>
@@ -139,6 +141,8 @@
<include name="conditional-preprocessor/**"/>
<include name="daemon/**"/>
<include name="daemon-common/**"/>
<include name="build-common/**"/>
<include name="incremental-compilation-impl/**"/>
<include name="util/**"/>
<include name="util.runtime/**"/>
<include name="light-classes/**"/>
@@ -245,6 +249,8 @@
<fileset dir="compiler/conditional-preprocessor/src"/>
<fileset dir="compiler/daemon/src"/>
<fileset dir="compiler/daemon/daemon-common/src"/>
<fileset dir="build-common/src"/>
<fileset dir="compiler/incremental-compilation-impl/src"/>
<fileset dir="compiler/container/src"/>
<fileset dir="compiler/frontend/src"/>
<fileset dir="compiler/resolution/src"/>
@@ -684,54 +690,6 @@
<pack-compiler-for-maven/>
</target>
<target name="kotlin-build-common">
<cleandir dir="${output}/classes/kotlin-build-common"/>
<javac2 destdir="${output}/classes/kotlin-build-common" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false"
source="${java.target}" target="${java.target}">
<withKotlin modulename="kotlin-build-common">
<compilerarg value="-version"/>
</withKotlin>
<skip pattern="kotlin/Metadata"/>
<src>
<pathelement path="build-common/src"/>
</src>
<classpath>
<pathelement path="${bootstrap.runtime}"/>
<pathelement path="${bootstrap.reflect}"/>
<pathelement path="${bootstrap.script.runtime}"/>
<pathelement path="${idea.sdk}/lib/util.jar"/>
<pathelement path="${kotlin-home}/lib/kotlin-compiler.jar"/>
</classpath>
</javac2>
<jar destfile="${kotlin-home}/lib/kotlin-build-common.jar">
<fileset dir="${output}/classes/kotlin-build-common"/>
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
<manifest>
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
<attribute name="Implementation-Vendor" value="${manifest.impl.vendor}"/>
<attribute name="Implementation-Title" value="${manifest.impl.title.kotlin.build.common}"/>
<attribute name="Implementation-Version" value="${build.number}"/>
</manifest>
</jar>
<jar jarfile="${output}/kotlin-build-common-sources.jar">
<fileset dir="build-common/src"/>
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
<manifest>
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
<attribute name="Implementation-Vendor" value="${manifest.impl.vendor}"/>
<attribute name="Implementation-Title" value="${manifest.impl.title.kotlin.build.common.sources}"/>
<attribute name="Implementation-Version" value="${build.number}"/>
</manifest>
</jar>
</target>
<target name="kotlin-build-common-test">
<cleandir dir="${output}/classes/kotlin-build-common-test"/>
@@ -739,7 +697,10 @@
source="${java.target}" target="${java.target}">
<withKotlin modulename="kotlin-build-common"/>
<skip pattern="kotlin/Metadata"/>
<src path="build-common/test"/>
<src>
<pathelement path="build-common/test"/>
<pathelement path="compiler/incremental-compilation-impl/test"/>
</src>
<classpath>
<pathelement path="${bootstrap.runtime}"/>
<pathelement path="${bootstrap.reflect}"/>
@@ -747,7 +708,6 @@
<pathelement path="${bootstrap.kotlin.test}"/>
<pathelement path="${protobuf.jar}"/>
<pathelement path="${idea.sdk}/lib/junit-4.12.jar"/>
<pathelement path="${kotlin-home}/lib/kotlin-build-common.jar"/>
<pathelement path="${kotlin-home}/lib/kotlin-compiler.jar"/>
</classpath>
</javac2>
@@ -902,7 +862,7 @@
<fileset dir="${basedir}/plugins/sam-with-receiver/sam-with-receiver-cli/src" includes="META-INF/services/**"/>
</jar>
</target>
<target name="annotation-processing-under-jdk8">
<property environment="env"/>
@@ -1313,7 +1273,7 @@
depends="builtins,stdlib,kotlin-test,core,reflection,pack-runtime,pack-runtime-sources,script-runtime,mock-runtime-for-test"/>
<target name="dist"
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,kotlin-build-common,ant-tools,runtime,kotlin-js-stdlib,android-extensions-compiler,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,annotation-processing-under-jdk8,daemon-client,kotlin-build-common-test"
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,ant-tools,runtime,kotlin-js-stdlib,android-extensions-compiler,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,annotation-processing-under-jdk8,daemon-client,kotlin-build-common-test"
description="Builds redistributables from sources"/>
<target name="dist-quick"

View File

@@ -65,6 +65,7 @@ import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReified;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
@@ -306,10 +307,11 @@ public class AsmUtil {
case ANNOTATION_CLASS:
return ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE;
default:
if (innerClass.getModality() == Modality.FINAL) {
Modality modality = innerClass.getModality();
if (modality == Modality.FINAL) {
return ACC_FINAL;
}
else if (innerClass.getModality() == Modality.ABSTRACT) {
else if (modality == Modality.ABSTRACT || modality == Modality.SEALED) {
return ACC_ABSTRACT;
}
}
@@ -342,7 +344,7 @@ public class AsmUtil {
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
Visibility memberVisibility = memberDescriptor.getVisibility();
if (AnnotationUtilKt.isInlineOnlyOrReified(memberDescriptor)) return ACC_PRIVATE;
if (isInlineOnlyOrReified(memberDescriptor)) return ACC_PRIVATE;
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
return ACC_PUBLIC;

View File

@@ -35,7 +35,7 @@ public class ClassBuilderMode {
}
public static ClassBuilderMode full(boolean generateSourceRetentionAnnotations) {
return generateSourceRetentionAnnotations ? KAPT2 : FULL;
return generateSourceRetentionAnnotations ? KAPT : FULL;
}
/**
@@ -47,15 +47,6 @@ public class ClassBuilderMode {
/* sourceRetention = */ false,
/* generateMultiFileFacadePartClasses = */ true);
/**
* Full function bodies, write annotations with the "source" retention.
*/
private final static ClassBuilderMode KAPT2 = new ClassBuilderMode(
/* bodies = */ true,
/* metadata = */ true,
/* sourceRetention = */ true,
/* generateMultiFileFacadePartClasses = */ false);
/**
* Generating light classes: Only function signatures
*/

View File

@@ -127,7 +127,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public final FrameMap myFrameMap;
public final MethodContext context;
private final Type returnType;
private final Type boxedReturnTypeForCoroutine;
private final CodegenStatementVisitor statementVisitor = new CodegenStatementVisitor(this);
private final MemberCodegen<?> parentCodegen;
@@ -161,14 +160,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
this.myFrameMap = frameMap;
this.context = context;
FunctionDescriptor descriptorForCoroutine = getOriginalLambdaDescriptorForCoroutine(context);
if (descriptorForCoroutine != null && descriptorForCoroutine.getReturnType() != null) {
this.returnType = typeMapper.mapReturnType(descriptorForCoroutine);
this.boxedReturnTypeForCoroutine = getBoxedReturnTypeForCoroutine(descriptorForCoroutine);
FunctionDescriptor originalSuspendDescriptor = getOriginalSuspendDescriptor(context);
if (originalSuspendDescriptor != null && originalSuspendDescriptor.getReturnType() != null) {
this.returnType = getBoxedReturnTypeForSuspend(originalSuspendDescriptor);
}
else {
this.returnType = returnType;
this.boxedReturnTypeForCoroutine = null;
}
this.parentCodegen = parentCodegen;
@@ -176,18 +173,31 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@NotNull
private Type getBoxedReturnTypeForCoroutine(FunctionDescriptor descriptorForCoroutine) {
assert descriptorForCoroutine.getReturnType() != null : "Uninitialized coroutine return type";
return AsmUtil.boxType(typeMapper.mapType(descriptorForCoroutine.getReturnType()));
private Type getBoxedReturnTypeForSuspend(FunctionDescriptor descriptorForSuspend) {
assert descriptorForSuspend.getReturnType() != null : "Uninitialized suspend return type";
return AsmUtil.boxType(typeMapper.mapType(descriptorForSuspend.getReturnType()));
}
@Nullable
private static FunctionDescriptor getOriginalLambdaDescriptorForCoroutine(MethodContext context) {
private static FunctionDescriptor getOriginalSuspendDescriptor(MethodContext context) {
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
if (originalCoroutineDescriptor != null) return originalCoroutineDescriptor;
if (context.getFunctionDescriptor().isSuspend()) {
return (FunctionDescriptor) CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(context.getFunctionDescriptor());
}
return null;
}
@Nullable
private static FunctionDescriptor getOriginalCoroutineDescriptor(MethodContext context) {
if ((context.getParentContext() instanceof ClosureContext) &&
(context.getParentContext().closure != null) &&
context.getParentContext().closure.isCoroutine()) {
return ((ClosureContext) context.getParentContext()).getCoroutineDescriptor();
}
return null;
}
@@ -351,7 +361,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
putStackValue(expr, type, value);
}
private void putStackValue(KtElement expr, Type type, StackValue value) {
private void putStackValue(@Nullable KtElement expr, @NotNull Type type, @NotNull StackValue value) {
// for repl store the result of the last line into special field
if (value.type != Type.VOID_TYPE && state.getReplSpecific().getShouldGenerateScriptResultValue()) {
ScriptContext context = getScriptContext();
@@ -944,14 +954,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange));
@SuppressWarnings("ConstantConditions") Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
StackValue result = invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator));
result.put(result.type, v);
result.put(Type.BOOLEAN_TYPE, v);
FunctionDescriptor hasNext = hasNextCall.getResultingDescriptor();
KotlinType type = hasNext.getReturnType();
assert type != null && KotlinTypeChecker.DEFAULT.isSubtypeOf(type, DescriptorUtilsKt.getBuiltIns(hasNext).getBooleanType());
Type asmType = asmType(type);
StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v);
v.ifeq(loopExit);
}
@@ -1775,7 +1779,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull
private static CallableDescriptor unwrapOriginalLambdaDescriptorForCoroutine(@NotNull MethodContext context) {
FunctionDescriptor coroutine = getOriginalLambdaDescriptorForCoroutine(context);
FunctionDescriptor coroutine = getOriginalSuspendDescriptor(context);
if (coroutine != null) return coroutine;
return context.getFunctionDescriptor();
}
@@ -2159,26 +2163,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : ExpressionCodegen.this.returnType;
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : null;
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : StackValue.none();
if (returnedExpression != null && valueToReturn != null) {
putStackValue(returnedExpression, returnType, valueToReturn);
}
putStackValue(returnedExpression, returnType, valueToReturn);
Label afterReturnLabel = new Label();
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel);
if (isNonLocalReturn) {
if (nonLocalReturn.boxedCoroutineReturnType != null && !nonLocalReturn.boxedCoroutineReturnType.equals(returnType)) {
StackValue.coerce(nonLocalReturn.returnType, nonLocalReturn.boxedCoroutineReturnType, v);
returnType = nonLocalReturn.boxedCoroutineReturnType;
}
InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName);
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
}
else {
emitLocalReturnInsn();
v.areturn(ExpressionCodegen.this.returnType);
}
v.mark(afterReturnLabel);
@@ -2213,7 +2210,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor containingFunction =
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
//FIRST_FUN_LABEL to prevent clashing with existing labels
return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL, null);
return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL);
} else {
//local
return null;
@@ -2225,49 +2222,49 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
assert element != null : "Expression should be not null " + expression.getText();
assert elementDescriptor != null : "Descriptor should be not null: " + element.getText();
Type boxedCoroutineReturnType =
elementDescriptor instanceof AnonymousFunctionDescriptor
&& ((AnonymousFunctionDescriptor) elementDescriptor).isCoroutine()
? getBoxedReturnTypeForCoroutine((FunctionDescriptor) elementDescriptor)
: null;
return new NonLocalReturnInfo(
typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName(),
boxedCoroutineReturnType
);
return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(elementDescriptor), expression.getLabelName());
}
}
return null;
}
@NotNull
private Type getReturnTypeForNonLocalReturn(DeclarationDescriptor elementDescriptor) {
return (elementDescriptor instanceof AnonymousFunctionDescriptor
&& ((AnonymousFunctionDescriptor) elementDescriptor).isCoroutine())
|| (elementDescriptor instanceof FunctionDescriptor && ((FunctionDescriptor) elementDescriptor).isSuspend())
? getBoxedReturnTypeForSuspend((FunctionDescriptor) elementDescriptor)
: typeMapper.mapReturnType((CallableDescriptor) elementDescriptor);
}
public void returnExpression(KtExpression expr) {
boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction;
// If generating body for named block-bodied function, generate it as sequence of statements
gen(expr, isBlockedNamedFunction ? Type.VOID_TYPE : returnType);
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
boolean isVoidCoroutineLambda =
originalCoroutineDescriptor != null && typeMapper.mapReturnType(originalCoroutineDescriptor).getSort() == Type.VOID;
// If generating body for named block-bodied function or Unit-typed coroutine lambda, generate it as sequence of statements
Type typeForExpression =
isBlockedNamedFunction || isVoidCoroutineLambda
? Type.VOID_TYPE
: returnType;
gen(expr, typeForExpression);
// If it does not end with return we should return something
// because if we don't there can be VerifyError (specific cases with Nothing-typed expressions)
if (!endsWithReturn(expr)) {
markLineNumber(expr, true);
if (isLambdaVoidBody(expr, returnType)) {
if (isLambdaVoidBody(expr, typeForExpression)) {
markLineNumber((KtFunctionLiteral) expr.getParent(), true);
}
if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) {
if (typeForExpression.getSort() == Type.VOID) {
StackValue.none().put(returnType, v);
}
emitLocalReturnInsn();
}
}
private void emitLocalReturnInsn() {
if (boxedReturnTypeForCoroutine != null && !boxedReturnTypeForCoroutine.equals(returnType)) {
StackValue.coerce(returnType, boxedReturnTypeForCoroutine, v);
v.areturn(boxedReturnTypeForCoroutine);
}
else {
v.areturn(returnType);
}
}
@@ -2778,9 +2775,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
StackValue result = callable.invokeMethodWithArguments(resolvedCall, receiver, this);
if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext)) {
// Suspension points should behave like they leave actual values on stack, while real methods return VOID
return new OperationStackValue(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda());
if (bindingContext.get(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall()) != null) {
// Suspend function's calls inside another suspend function should behave like they leave values of correct type,
// while real methods return java/lang/Object.
// NB: They are always in return position at the moment.
// If we didn't do this, StackValue.coerce would add proper CHECKCAST that would've failed in case of callee function
// returning SUSPENDED marker, which is instance of java/lang/Object.
return new OperationStackValue(returnType, ((OperationStackValue) result).getLambda());
}
return result;
@@ -2895,11 +2896,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
if (isSuspensionPoint) {
v.tconst(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall));
v.invokestatic(
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
"(Ljava/lang/Class;)V", false);
"()V", false
);
}
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
@@ -2918,23 +2919,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
@NotNull
private Type getSuspensionBoxedReturnTypeByResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor
: "Suspension point resolved call should be built on SimpleFunctionDescriptor";
FunctionDescriptor initialSignature =
((SimpleFunctionDescriptor) resolvedCall.getResultingDescriptor())
.getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION);
assert initialSignature != null : "Initial signature must be not null for suspension point";
KotlinType returnType = initialSignature.getReturnType();
assert returnType != null : "Return type of suspension point should not be null";
return typeMapper.mapType(TypeUtils.makeNullable(returnType));
}
@NotNull
private CallGenerator getOrCreateCallGenerator(
@NotNull CallableDescriptor descriptor,
@@ -4713,12 +4697,10 @@ The "returned" value of try expression with no finally is either the last expres
private final Type returnType;
private final String labelName;
private final Type boxedCoroutineReturnType;
private NonLocalReturnInfo(@NotNull Type type, @NotNull String name, @Nullable Type boxedCoroutineReturnType) {
private NonLocalReturnInfo(@NotNull Type type, @NotNull String name) {
returnType = type;
labelName = name;
this.boxedCoroutineReturnType = boxedCoroutineReturnType;
}
}

View File

@@ -48,7 +48,6 @@ import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
@@ -83,6 +82,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReified;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
@@ -863,7 +863,7 @@ public class FunctionCodegen {
// $default methods are never private to be accessible from other class files (e.g. inner) without the need of synthetic accessors
// $default methods are never protected to be accessible from subclass nested classes
int visibilityFlag = Visibilities.isPrivate(functionDescriptor.getVisibility()) ||
AnnotationUtilKt.isInlineOnlyOrReified(functionDescriptor) ?
isInlineOnlyOrReified(functionDescriptor) ?
AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
int flags = visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
if (!(functionDescriptor instanceof ConstructorDescriptor)) {

View File

@@ -268,9 +268,7 @@ public class JvmCodegenUtil {
@NotNull
public static CallableMemberDescriptor getDirectMember(@NotNull CallableMemberDescriptor descriptor) {
return descriptor instanceof PropertyAccessorDescriptor
? ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()
: descriptor;
return DescriptorUtils.getDirectMember(descriptor);
}
public static boolean isArgumentWhichWillBeInlined(@NotNull BindingContext bindingContext, @NotNull DeclarationDescriptor descriptor) {

View File

@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities;
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
import org.jetbrains.kotlin.storage.NullableLazyValue;
import org.jetbrains.kotlin.types.KotlinType;
@@ -39,6 +38,7 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReified;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
@@ -638,7 +638,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
boolean withinInline,
boolean isSuperCall
) {
if (AnnotationUtilKt.isInlineOnlyOrReified(unwrappedDescriptor)) return false;
if (isInlineOnlyOrReified(unwrappedDescriptor)) return false;
return isSuperCall && withinInline ||
(accessFlag & ACC_PRIVATE) != 0 ||

View File

@@ -162,36 +162,12 @@ class CoroutineTransformerMethodVisitor(
}
AFTER_SUSPENSION_POINT_MARKER_NAME -> {
assert(beforeSuspensionPointMarkerStack.isNotEmpty()) { "Expected non-empty stack beforeSuspensionPointMarkerStack" }
val beforeSuspensionPointMarker = beforeSuspensionPointMarkerStack.pop()
assert(beforeSuspensionPointMarker.previous is LdcInsnNode) {
"Instruction before BEFORE_SUSPENSION_POINT_MARKER_NAME should be LDC with expected return type, " +
"but ${beforeSuspensionPointMarker.previous} was found"
}
val fakeReturnValueInsns = mutableListOf<AbstractInsnNode>()
val suspensionPoint = SuspensionPoint(
suspensionCallBegin = beforeSuspensionPointMarker,
suspensionCallEnd = methodInsn,
fakeReturnValueInsns = fakeReturnValueInsns,
returnType = (beforeSuspensionPointMarker.previous as LdcInsnNode).cst as Type)
suspensionPoints.add(suspensionPoint)
// Drop type info from marker
methodNode.instructions.remove(beforeSuspensionPointMarker.previous)
beforeSuspensionPointMarker.desc = "()V"
assert(suspensionPoint.returnType != Type.VOID_TYPE) { "Suspension point can't be VOID" }
// Checkcast only is needed to tell analyzer what type exactly should be returned from suspension point
// This type is used when for restoring spilled variables into fields
val checkCast = TypeInsnNode(Opcodes.CHECKCAST, suspensionPoint.returnType.internalName)
methodNode.instructions.insertBefore(
suspensionPoint.suspensionCallEnd, checkCast
suspensionPoints.add(
SuspensionPoint(
suspensionCallBegin = beforeSuspensionPointMarkerStack.pop(),
suspensionCallEnd = methodInsn
)
)
fakeReturnValueInsns.add(checkCast)
}
}
}
@@ -224,7 +200,7 @@ class CoroutineTransformerMethodVisitor(
for (suspension in suspensionPoints) {
val suspensionCallBegin = suspension.suspensionCallBegin
val suspensionCallEnd = suspension.suspensionCallEnd
assert(frames[suspensionCallEnd.next.index()]?.stackSize == (if (suspension.returnType.sort == Type.VOID) 0 else 1)) {
assert(frames[suspensionCallEnd.next.index()]?.stackSize == 1) {
"Stack should be spilled before suspension call"
}
@@ -338,9 +314,6 @@ class CoroutineTransformerMethodVisitor(
)
)
// Drop default value that purpose was to simulate returned value by suspension method
suspension.fakeReturnValueInsns.forEach { methodNode.instructions.remove(it) }
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
dup()
load(suspendMarkerVarIndex, AsmTypes.OBJECT_TYPE)
@@ -371,7 +344,6 @@ class CoroutineTransformerMethodVisitor(
load(1, AsmTypes.OBJECT_TYPE)
visitLabel(continuationLabelAfterLoadedResult.label)
StackValue.coerce(AsmTypes.OBJECT_TYPE, suspension.returnType, this)
})
}
@@ -500,9 +472,7 @@ private class SuspensionPoint(
// INVOKESTATIC beforeSuspensionMarker
val suspensionCallBegin: AbstractInsnNode,
// INVOKESTATIC afterSuspensionMarker
val suspensionCallEnd: AbstractInsnNode,
val fakeReturnValueInsns: List<AbstractInsnNode>,
val returnType: Type
val suspensionCallEnd: AbstractInsnNode
) {
lateinit var tryCatchBlocksContinuationLabel: LabelNode
}

View File

@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
@@ -70,6 +69,7 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.hasInlineOnlyAnnotation;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
public class InlineCodegen extends CallGenerator {
@@ -436,7 +436,7 @@ public class InlineCodegen extends CallGenerator {
node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
"Method inlining " + callElement.getText(),
createNestedSourceMapper(nodeAndSmap, sourceMapper), info.getCallSiteInfo(),
AnnotationUtilKt.hasInlineOnlyAnnotation(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null
hasInlineOnlyAnnotation(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null
); //with captured
LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);

View File

@@ -224,7 +224,7 @@ public class KotlinTypeMapper {
}
}
CallableMemberDescriptor directMember = getDirectMember(descriptor);
CallableMemberDescriptor directMember = DescriptorUtils.getDirectMember(descriptor);
if (directMember instanceof DeserializedCallableMemberDescriptor) {
String facadeFqName = getPackageMemberOwnerInternalName((DeserializedCallableMemberDescriptor) directMember, publicFacade);
@@ -946,7 +946,7 @@ public class KotlinTypeMapper {
return null;
}
descriptor = getDirectMember(descriptor);
descriptor = DescriptorUtils.getDirectMember(descriptor);
assert descriptor instanceof DeserializedCallableMemberDescriptor :
"Descriptor without sources should be instance of DeserializedCallableMemberDescriptor, but: " +
descriptor;
@@ -1039,7 +1039,7 @@ public class KotlinTypeMapper {
writeVoidReturn(sw);
}
else {
CallableMemberDescriptor directMember = getDirectMember(f);
CallableMemberDescriptor directMember = DescriptorUtils.getDirectMember(f);
KotlinType thisIfNeeded = null;
if (OwnerKind.DEFAULT_IMPLS == kind) {
ReceiverTypeAndTypeParameters receiverTypeAndTypeParameters = TypeMapperUtilsKt.patchTypeParametersForDefaultImplMethod(directMember);

View File

@@ -42,7 +42,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
import org.jetbrains.kotlin.serialization.builtins.BuiltInsSerializerExtension
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment.Companion.METADATA_FILE_EXTENSION
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment.Companion.DOT_METADATA_FILE_EXTENSION
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
import java.io.ByteArrayOutputStream
import java.io.DataOutputStream
@@ -132,10 +132,10 @@ open class MetadataSerializer(private val dependOnOldBuiltIns: Boolean) {
private fun getPackageFilePath(packageFqName: FqName, fileName: String): String =
packageFqName.asString().replace('.', '/') + "/" +
PackagePartClassUtils.getPartClassName(fileName.substringBeforeLast(".kt")) + METADATA_FILE_EXTENSION
PackagePartClassUtils.getPartClassName(fileName.substringBeforeLast(".kt")) + DOT_METADATA_FILE_EXTENSION
private fun getClassFilePath(classId: ClassId): String =
classId.asSingleFqName().asString().replace('.', '/') + METADATA_FILE_EXTENSION
classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION
protected inner class PackageSerializer(
private val classes: Collection<DeclarationDescriptor>,

View File

@@ -109,6 +109,9 @@ object JvmRuntimeVersionsConsistencyChecker {
languageVersionSettings: LanguageVersionSettings?,
classpathJarRoots: List<VirtualFile>
) {
// TODO: write runtime version to Maven artifacts and enable these checks
return
val runtimeJarsInfo = collectRuntimeJarsInfo(classpathJarRoots)
if (runtimeJarsInfo.hasAnyJarsToCheck) {
val languageVersion = languageVersionSettings?.let { MavenComparableVersion(it.languageVersion) } ?: CURRENT_COMPILER_VERSION

View File

@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
import org.jetbrains.kotlin.compiler.plugin.PluginCliOptionProcessingException
import org.jetbrains.kotlin.compiler.plugin.cliPluginUsageString
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
@@ -267,10 +266,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, components)
}
}
services.get(SourceRetentionAnnotationHandler::class.java)?.let { handler ->
configuration.put(JVMConfigurationKeys.SOURCE_RETENTION_ANNOTATION_HANDLER, handler)
}
}
/**

View File

@@ -39,13 +39,13 @@ class JvmCliVirtualFileFinder(
override fun findMetadata(classId: ClassId): InputStream? {
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.METADATA_FILE_EXTENSION)?.inputStream
return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION)?.inputStream
}
override fun hasMetadataPackage(fqName: FqName): Boolean {
var found = false
index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ ->
found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION.substring(1) }
found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION }
!found
})
return found

View File

@@ -313,7 +313,7 @@ class KotlinCoreEnvironment private constructor(
companion object {
init {
System.getProperties().setProperty("idea.plugins.compatible.build", "162.9999")
setCompatibleBuild()
}
private val APPLICATION_LOCK = Object()
@@ -323,6 +323,7 @@ class KotlinCoreEnvironment private constructor(
@JvmStatic fun createForProduction(
parentDisposable: Disposable, configuration: CompilerConfiguration, configFilePaths: List<String>
): KotlinCoreEnvironment {
setCompatibleBuild()
val appEnv = getOrCreateApplicationEnvironmentForProduction(configuration, configFilePaths)
// Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally
// breaks a lot of tests, therefore it is disabled for production and enabled for tests
@@ -345,6 +346,11 @@ class KotlinCoreEnvironment private constructor(
return environment
}
@JvmStatic
private fun setCompatibleBuild() {
System.getProperties().setProperty("idea.plugins.compatible.build", "162.9999")
}
@TestOnly
@JvmStatic fun createForTests(
parentDisposable: Disposable, configuration: CompilerConfiguration, extensionConfigs: List<String>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="build-common" />
<orderEntry type="module" module-name="cli-common" />
<orderEntry type="module" module-name="daemon-client" />
<orderEntry type="module" module-name="daemon-common" />
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="preloader" />
<orderEntry type="module" module-name="util" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
</component>
</module>

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2010-2016 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.compilerRunner
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.utils.KotlinPaths
open class CompilerEnvironment(
val services: Services,
val messageCollector: MessageCollector,
open val outputItemsCollector: OutputItemsCollector
)

View File

@@ -0,0 +1,180 @@
/*
* 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.compilerRunner
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.xml.sax.Attributes
import org.xml.sax.InputSource
import org.xml.sax.SAXException
import org.xml.sax.helpers.DefaultHandler
import javax.xml.parsers.SAXParser
import javax.xml.parsers.SAXParserFactory
import java.io.IOException
import java.io.Reader
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.Companion.NO_LOCATION
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil.reportException
object CompilerOutputParser {
fun parseCompilerMessagesFromReader(messageCollector: MessageCollector, reader: Reader, collector: OutputItemsCollector) {
// Sometimes the compiler doesn't output valid XML.
// Example: error in command line arguments passed to the compiler.
// The compiler will print the usage and the SAX parser will break.
// In this case, we want to read everything from this stream and report it as an IDE error.
val stringBuilder = StringBuilder()
val wrappingReader = object : Reader() {
@Throws(IOException::class)
override fun read(cbuf: CharArray, off: Int, len: Int): Int {
val read = reader.read(cbuf, off, len)
stringBuilder.append(cbuf, off, len)
return read
}
@Throws(IOException::class)
override fun close() {
// Do nothing:
// If the SAX parser sees a syntax error, it throws an exception
// and calls close() on the reader.
// We prevent hte reader from being closed here, and close it later,
// when all the text is read from it
}
}
try {
val factory = SAXParserFactory.newInstance()
val parser = factory.newSAXParser()
parser.parse(InputSource(wrappingReader), CompilerOutputSAXHandler(messageCollector, collector))
}
catch (e: Throwable) {
// Load all the text into the stringBuilder
try {
// This will not close the reader (see the wrapper above)
FileUtil.loadTextAndClose(wrappingReader)
}
catch (ioException: IOException) {
reportException(messageCollector, ioException)
}
val message = stringBuilder.toString()
reportException(messageCollector, IllegalStateException(message, e))
messageCollector.report(ERROR, message, NO_LOCATION)
}
finally {
try {
reader.close()
}
catch (e: IOException) {
reportException(messageCollector, e)
}
}
}
private class CompilerOutputSAXHandler(private val messageCollector: MessageCollector, private val collector: OutputItemsCollector) : DefaultHandler() {
private val message = StringBuilder()
private val tags = Stack<String>()
private var path: String? = null
private var line: Int = 0
private var column: Int = 0
@Throws(SAXException::class)
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
tags.push(qName)
message.setLength(0)
path = attributes.getValue("path")
line = safeParseInt(attributes.getValue("line"), -1)
column = safeParseInt(attributes.getValue("column"), -1)
}
@Throws(SAXException::class)
override fun characters(ch: CharArray?, start: Int, length: Int) {
if (tags.size == 1) {
// We're directly inside the root tag: <MESSAGES>
val message = String(ch!!, start, length)
if (!message.trim { it <= ' ' }.isEmpty()) {
messageCollector.report(ERROR, "Unhandled compiler output: " + message, NO_LOCATION)
}
}
else {
message.append(ch, start, length)
}
}
@Throws(SAXException::class)
override fun endElement(uri: String?, localName: String, qName: String) {
if (tags.size == 1) {
// We're directly inside the root tag: <MESSAGES>
return
}
val qNameLowerCase = qName.toLowerCase()
var category: CompilerMessageSeverity? = CATEGORIES[qNameLowerCase]
if (category == null) {
messageCollector.report(ERROR, "Unknown compiler message tag: " + qName, NO_LOCATION)
category = INFO
}
val text = message.toString()
if (category == OUTPUT) {
reportToCollector(text)
}
else {
messageCollector.report(category, text, CompilerMessageLocation.create(path, line, column, null))
}
tags.pop()
}
private fun reportToCollector(text: String) {
val output = OutputMessageUtil.parseOutputMessage(text)
if (output != null) {
collector.add(output.sourceFiles, output.outputFile)
}
}
companion object {
private val CATEGORIES = mapOf(
"error" to ERROR,
"warning" to WARNING,
"logging" to LOGGING,
"output" to OUTPUT,
"exception" to EXCEPTION,
"info" to INFO,
"messages" to INFO)
private fun safeParseInt(value: String?, defaultValue: Int): Int {
if (value == null) {
return defaultValue
}
try {
return Integer.parseInt(value.trim { it <= ' ' })
}
catch (e: NumberFormatException) {
return defaultValue
}
}
}
}
}

View File

@@ -0,0 +1,206 @@
/*
* 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.compilerRunner
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.daemon.client.CompilationServices
import org.jetbrains.kotlin.daemon.client.DaemonReportMessage
import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets
import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import java.io.BufferedReader
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.StringReader
import java.util.*
import java.util.concurrent.TimeUnit
interface KotlinLogger {
fun error(msg: String)
fun warn(msg: String)
fun info(msg: String)
fun debug(msg: String)
}
abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
protected val K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
protected val K2JS_COMPILER = "org.jetbrains.kotlin.cli.js.K2JSCompiler"
protected val K2METADATA_COMPILER = "org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler"
protected val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString()
protected abstract val log: KotlinLogger
class DaemonConnection(val daemon: CompileService?, val sessionId: Int = CompileService.NO_SESSION)
protected abstract fun getDaemonConnection(environment: Env): DaemonConnection
@Synchronized
protected fun newDaemonConnection(compilerId: CompilerId, flagFile: File, environment: Env): DaemonConnection {
val daemonOptions = configureDaemonOptions()
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
val daemonReportMessages = ArrayList<DaemonReportMessage>()
val profiler = if (daemonOptions.reportPerf) WallAndThreadAndMemoryTotalProfiler(withGC = false) else DummyProfiler()
val connection = profiler.withMeasure(null) {
val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true)
DaemonConnection(daemon, daemon?.leaseCompileSession(flagFile.absolutePath)?.get() ?: CompileService.NO_SESSION)
}
for (msg in daemonReportMessages) {
environment.messageCollector.report(CompilerMessageSeverity.INFO,
(if (msg.category == DaemonReportCategory.EXCEPTION && connection.daemon == null) "Falling back to compilation without daemon due to error: " else "") + msg.message,
CompilerMessageLocation.NO_LOCATION)
}
fun reportTotalAndThreadPerf(message: String, daemonOptions: DaemonOptions, messageCollector: MessageCollector, profiler: Profiler) {
if (daemonOptions.reportPerf) {
fun Long.ms() = TimeUnit.NANOSECONDS.toMillis(this)
val counters = profiler.getTotalCounters()
messageCollector.report(CompilerMessageSeverity.INFO,
"PERF: $message ${counters.time.ms()} ms, thread ${counters.threadTime.ms()}",
CompilerMessageLocation.NO_LOCATION)
}
}
reportTotalAndThreadPerf("Daemon connect", daemonOptions, environment.messageCollector, profiler)
return connection
}
protected fun processCompilerOutput(
environment: Env,
stream: ByteArrayOutputStream,
exitCode: ExitCode?
) {
val reader = BufferedReader(StringReader(stream.toString()))
CompilerOutputParser.parseCompilerMessagesFromReader(environment.messageCollector, reader, environment.outputItemsCollector)
if (ExitCode.INTERNAL_ERROR == exitCode) {
reportInternalCompilerError(environment.messageCollector)
}
}
protected fun reportInternalCompilerError(messageCollector: MessageCollector): ExitCode {
messageCollector.report(ERROR, "Compiler terminated with internal error", CompilerMessageLocation.NO_LOCATION)
return ExitCode.INTERNAL_ERROR
}
protected fun runCompiler(
compilerClassName: String,
arguments: CommonCompilerArguments,
additionalArguments: String,
environment: Env): ExitCode {
return try {
val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments)
argumentsList.addAll(additionalArguments.split(" "))
val argsArray = argumentsList.toTypedArray()
doRunCompiler(compilerClassName, argsArray, environment)
}
catch (e: Throwable) {
MessageCollectorUtil.reportException(environment.messageCollector, e)
reportInternalCompilerError(environment.messageCollector)
}
}
protected abstract fun doRunCompiler(
compilerClassName: String,
argsArray: Array<String>,
environment: Env
): ExitCode
/**
* Returns null if could not connect to daemon
*/
protected open fun compileWithDaemon(
compilerClassName: String,
argsArray: Array<String>,
environment: Env
): ExitCode? {
val compilerOut = ByteArrayOutputStream()
val daemonOut = ByteArrayOutputStream()
val services = CompilationServices(
incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java),
compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java))
val targetPlatform = when (compilerClassName) {
K2JVM_COMPILER -> CompileService.TargetPlatform.JVM
K2JS_COMPILER -> CompileService.TargetPlatform.JS
K2METADATA_COMPILER -> CompileService.TargetPlatform.METADATA
else -> throw IllegalArgumentException("Unknown compiler type $compilerClassName")
}
val res: Int = withDaemon(environment, retryOnConnectionError = true) { daemon, sessionId ->
KotlinCompilerClient.incrementalCompile(daemon, sessionId, targetPlatform, argsArray, services, compilerOut, daemonOut)
} ?: return null
val exitCode = exitCodeFromProcessExitCode(res)
processCompilerOutput(environment, compilerOut, exitCode)
BufferedReader(StringReader(daemonOut.toString())).forEachLine {
environment.messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION)
}
return exitCode
}
protected fun <T> withDaemon(environment: Env, retryOnConnectionError: Boolean, fn: (CompileService, sessionId: Int)->T): T? {
fun retryOrFalse(e: Exception): T? {
if (retryOnConnectionError) {
log.debug("retrying once on daemon connection error: ${e.message}")
return withDaemon(environment, retryOnConnectionError = false, fn = fn)
}
log.info("daemon connection error: ${e.message}")
return null
}
log.debug("Try to connect to daemon")
val connection = getDaemonConnection(environment)
if (connection.daemon != null) {
log.info("Connected to daemon")
try {
return fn(connection.daemon, connection.sessionId)
}
catch (e: java.rmi.ConnectException) {
return retryOrFalse(e)
}
catch (e: java.rmi.UnmarshalException) {
return retryOrFalse(e)
}
}
log.info("Daemon not found")
return null
}
protected fun exitCodeFromProcessExitCode(code: Int): ExitCode {
val exitCode = ExitCode.values().find { it.code == code }
if (exitCode != null) return exitCode
log.debug("Could not find exit code by value: $code")
return if (code == 0) ExitCode.OK else ExitCode.COMPILATION_ERROR
}
}

View File

@@ -31,7 +31,8 @@ interface CompileService : Remote {
enum class TargetPlatform : Serializable {
JVM,
JS
JS,
METADATA
}
companion object {
@@ -125,6 +126,19 @@ interface CompileService : Remote {
operationsTracer: RemoteOperationsTracer?
): CallResult<Int>
@Throws(RemoteException::class)
fun serverSideJvmIC(
sessionId: Int,
args: Array<out String>,
servicesFacade: IncrementalCompilationServicesFacade,
compilerOutputStream: RemoteOutputStream,
serviceOutputStream: RemoteOutputStream,
operationsTracer: RemoteOperationsTracer?
): CallResult<Int>
@Throws(RemoteException::class)
fun clearJarCache()
@Throws(RemoteException::class)
fun leaseReplSession(
aliveFlagPath: String?,

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2010-2016 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.daemon.common
import java.io.File
import java.io.Serializable
import java.rmi.Remote
import java.rmi.RemoteException
interface IncrementalCompilationServicesFacade : Remote {
@Throws(RemoteException::class)
fun areFileChangesKnown(): Boolean
@Throws(RemoteException::class)
fun modifiedFiles(): List<File>?
@Throws(RemoteException::class)
fun deletedFiles(): List<File>?
@Throws(RemoteException::class)
fun workingDir(): File
@Throws(RemoteException::class)
fun customCacheVersionFileName(): String
@Throws(RemoteException::class)
fun customCacheVersion(): Int
// ICReporter
@Throws(RemoteException::class)
fun shouldReportIC(): Boolean
@Throws(RemoteException::class)
fun reportIC(message: String)
@Throws(RemoteException::class)
fun reportCompileIteration(files: Iterable<File>, exitCode: Int)
// AnnotationFileUpdater
@Throws(RemoteException::class)
fun hasAnnotationsFileUpdater(): Boolean
@Throws(RemoteException::class)
fun updateAnnotations(outdatedClassesJvmNames: Iterable<String>)
@Throws(RemoteException::class)
fun revert()
// ChangesRegistry
@Throws(RemoteException::class)
fun registerChanges(timestamp: Long, dirtyData: SimpleDirtyData)
@Throws(RemoteException::class)
fun unknownChanges(timestamp: Long)
@Throws(RemoteException::class)
fun getChanges(artifact: File, sinceTS: Long): Iterable<SimpleDirtyData>?
}
class SimpleDirtyData(
val dirtyLookupSymbols: List<String>,
val dirtyClassesFqNames: List<String>
) : Serializable

View File

@@ -12,5 +12,8 @@
<orderEntry type="module" module-name="util" />
<orderEntry type="library" name="intellij-core" level="project" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="incremental-compilation-impl" />
<orderEntry type="module" module-name="build-common" />
<orderEntry type="module" module-name="descriptor.loader.java" />
</component>
</module>

View File

@@ -20,20 +20,34 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.impl.ZipHandler
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser
import org.jetbrains.kotlin.cli.common.repl.ReplCheckResult
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.daemon.incremental.*
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.utils.addToStdlib.check
import java.io.BufferedOutputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.rmi.NoSuchObjectException
@@ -306,6 +320,63 @@ class CompileServiceImpl(
}
}
override fun serverSideJvmIC(
sessionId: Int,
args: Array<out String>,
servicesFacade: IncrementalCompilationServicesFacade,
compilerOutputStream: RemoteOutputStream,
serviceOutputStream: RemoteOutputStream,
operationsTracer: RemoteOperationsTracer?
): CompileService.CallResult<Int> {
return doCompile(sessionId, args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, eventManager, profiler ->
val reporter = RemoteICReporter(servicesFacade)
val annotationFileUpdater = if (servicesFacade.hasAnnotationsFileUpdater()) RemoteAnnotationsFileUpdater(servicesFacade) else null
// these flags do not have any effect on the compiler (only on caches, incremental compilation logic, jps plugin)
// so it's OK to just set them true
IncrementalCompilation.setIsEnabled(true)
IncrementalCompilation.setIsExperimental(true)
val k2jvmArgs = K2JVMCompilerArguments()
(compiler[CompileService.TargetPlatform.JVM] as K2JVMCompiler).parseArguments(args, k2jvmArgs)
val moduleFile = k2jvmArgs.module?.let(::File)
assert(moduleFile?.exists() ?: false) { "Module does not exist ${k2jvmArgs.module}" }
val renderer = MessageRenderer.XML
val messageCollector = PrintingMessageCollector(printStream, renderer, k2jvmArgs.verbose)
val filteringMessageCollector = FilteringMessageCollector(messageCollector) { it == CompilerMessageSeverity.ERROR }
val parsedModule = ModuleXmlParser.parseModuleScript(k2jvmArgs.module, filteringMessageCollector)
val javaSourceRoots = parsedModule.modules.flatMapTo(HashSet()) { it.getJavaSourceRoots().map { File(it.path) } }
val allKotlinFiles = parsedModule.modules.flatMap { it.getSourceFiles().map(::File) }
k2jvmArgs.friendPaths = parsedModule.modules.flatMap(Module::getFriendPaths).toTypedArray()
val changedFiles = if (servicesFacade.areFileChangesKnown()) {
ChangedFiles.Known(servicesFacade.modifiedFiles()!!, servicesFacade.deletedFiles()!!)
}
else {
ChangedFiles.Unknown()
}
val artifactChanges = RemoteArtifactChangesProvider(servicesFacade)
val changesRegistry = RemoteChangesRegostry(servicesFacade)
val workingDir = servicesFacade.workingDir()
val versions = commonCacheVersions(workingDir) +
customCacheVersion(servicesFacade.customCacheVersion(), servicesFacade.customCacheVersionFileName(), workingDir, forceEnable = true)
try {
printStream.print(renderer.renderPreamble())
IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions, reporter, annotationFileUpdater,
artifactChanges, changesRegistry)
.compile(allKotlinFiles, k2jvmArgs, messageCollector, { changedFiles })
}
finally {
printStream.print(renderer.renderConclusion())
}
}
}
override fun leaseReplSession(
aliveFlagPath: String?,
targetPlatform: CompileService.TargetPlatform,
@@ -610,7 +681,7 @@ class CompileServiceImpl(
}
}
private fun clearJarCache() {
override fun clearJarCache() {
ZipHandler.clearFileAccessorCache()
(KotlinCoreEnvironment.applicationEnvironment?.jarFileSystem as? CoreJarFileSystem)?.clearHandlersCache()
}

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.daemon
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.js.K2JSCompiler
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
import org.jetbrains.kotlin.daemon.common.*
import java.io.File
import java.io.IOException
@@ -125,9 +126,11 @@ object KotlinCompileDaemon {
val compilerSelector = object : CompilerSelector {
private val jvm by lazy { K2JVMCompiler() }
private val js by lazy { K2JSCompiler() }
private val metadata by lazy { K2MetadataCompiler() }
override fun get(targetPlatform: CompileService.TargetPlatform): CLICompiler<*> = when (targetPlatform) {
CompileService.TargetPlatform.JVM -> jvm
CompileService.TargetPlatform.JS -> js
CompileService.TargetPlatform.METADATA -> metadata
}
}
// timer with a daemon thread, meaning it should not prevent JVM to exit normally

View File

@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade
import org.jetbrains.kotlin.daemon.common.DummyProfiler
import org.jetbrains.kotlin.daemon.common.Profiler
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
class RemoteIncrementalCompilationComponentsClient(val facade: CompilerCallbackServicesFacade, eventManger: EventManger, val profiler: Profiler = DummyProfiler()) : IncrementalCompilationComponents {

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2010-2016 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.daemon.incremental
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
import org.jetbrains.kotlin.incremental.ICReporter
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
internal class RemoteAnnotationsFileUpdater(private val servicesFacade: IncrementalCompilationServicesFacade) : AnnotationFileUpdater {
override fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>) {
servicesFacade.updateAnnotations(outdatedClasses.map { it.internalName })
}
override fun revert() {
servicesFacade.revert()
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2010-2016 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.daemon.incremental
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
import org.jetbrains.kotlin.incremental.DirtyData
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
import java.io.File
class RemoteArtifactChangesProvider(private val servicesFacade: IncrementalCompilationServicesFacade) : ArtifactChangesProvider {
override fun getChanges(artifact: File, sinceTS: Long): Iterable<DirtyData>? =
servicesFacade.getChanges(artifact, sinceTS)?.map { it.toDirtyData() }
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2010-2016 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.daemon.incremental
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
import org.jetbrains.kotlin.incremental.DirtyData
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
internal class RemoteChangesRegostry(private val servicesFacade: IncrementalCompilationServicesFacade) : ChangesRegistry {
override fun unknownChanges(timestamp: Long) {
servicesFacade.unknownChanges(timestamp)
}
override fun registerChanges(timestamp: Long, dirtyData: DirtyData) {
servicesFacade.registerChanges(timestamp, dirtyData.toSimpleDirtyData())
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2010-2016 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.daemon.incremental
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
import org.jetbrains.kotlin.incremental.ICReporter
import java.io.File
internal class RemoteICReporter(private val servicesFacade: IncrementalCompilationServicesFacade) : ICReporter() {
override fun report(message: () -> String) {
if (servicesFacade.shouldReportIC()) {
servicesFacade.reportIC(message())
}
}
override fun reportCompileIteration(sourceFiles: Iterable<File>, exitCode: ExitCode) {
if (servicesFacade.shouldReportIC()) {
servicesFacade.reportCompileIteration(sourceFiles, exitCode.code)
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2010-2016 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.daemon.incremental
import org.jetbrains.kotlin.daemon.common.SimpleDirtyData
import org.jetbrains.kotlin.incremental.DirtyData
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.name.FqName
fun SimpleDirtyData.toDirtyData(): DirtyData {
val dirtyClassesFqNames = dirtyClassesFqNames.map(::FqName)
val dirtyLookupSymbols = dirtyLookupSymbols.map {
LookupSymbol(scope = it.substringBeforeLast("."), name = it.substringAfterLast("."))
}
return DirtyData(dirtyLookupSymbols, dirtyClassesFqNames)
}
fun DirtyData.toSimpleDirtyData(): SimpleDirtyData {
return SimpleDirtyData(dirtyClassesFqNames = dirtyClassesFqNames.map(FqName::asString),
dirtyLookupSymbols = dirtyLookupSymbols.map { "${it.scope}.${it.name}" })
}

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.config;
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler;
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents;
import org.jetbrains.kotlin.modules.Module;
import org.jetbrains.kotlin.script.KotlinScriptDefinition;
@@ -94,9 +93,6 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<File> MODULE_XML_FILE =
CompilerConfigurationKey.create("path to module.xml");
public static final CompilerConfigurationKey<SourceRetentionAnnotationHandler> SOURCE_RETENTION_ANNOTATION_HANDLER =
CompilerConfigurationKey.create("source retention annotation handler");
public static final CompilerConfigurationKey<String> DECLARATIONS_JSON_PATH =
CompilerConfigurationKey.create("path to declarations output");

View File

@@ -177,7 +177,7 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
val resolverForProject = createResolverForProject()
fun computeDependencyDescriptors(module: M): List<ModuleDescriptorImpl> {
val orderedDependencies = LinkedHashSet(firstDependency.singletonOrEmptyList() + module.dependencies())
val orderedDependencies = firstDependency.singletonOrEmptyList() + module.dependencies()
val dependenciesDescriptors = orderedDependencies.mapTo(ArrayList<ModuleDescriptorImpl>()) {
dependencyInfo ->
resolverForProject.descriptorForModule(dependencyInfo as M)

View File

@@ -234,6 +234,7 @@ public interface Errors {
DiagnosticFactory0<KtSuperTypeEntry> SUPERTYPE_NOT_INITIALIZED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> DELEGATION_NOT_TO_INTERFACE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory2<KtDeclaration, CallableMemberDescriptor, List<CallableMemberDescriptor>> DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<KtTypeReference> SUPERTYPE_NOT_A_CLASS_OR_INTERFACE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> SUPERTYPE_IS_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR);
@@ -511,6 +512,8 @@ public interface Errors {
DiagnosticFactory0<KtParameter> HEADER_DECLARATION_WITH_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstructorDelegationCall> HEADER_CLASS_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtParameter> HEADER_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstructor<?>> HEADER_ENUM_CONSTRUCTOR = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtEnumEntry> HEADER_ENUM_ENTRY_WITH_BODY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> HEADER_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeAlias> IMPL_TYPE_ALIAS_NOT_TO_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);

View File

@@ -265,6 +265,8 @@ public class DefaultErrorMessages {
MAP.put(HEADER_DECLARATION_WITH_DEFAULT_PARAMETER, "Header declaration cannot have parameters with default values");
MAP.put(HEADER_CLASS_CONSTRUCTOR_DELEGATION_CALL, "Explicit delegation call for constructor of a header class is not allowed");
MAP.put(HEADER_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Header class constructor cannot have a property parameter");
MAP.put(HEADER_ENUM_CONSTRUCTOR, "Header enum class cannot have a constructor");
MAP.put(HEADER_ENUM_ENTRY_WITH_BODY, "Header enum entry cannot have a body");
MAP.put(HEADER_PROPERTY_INITIALIZER, "Header property cannot have an initializer");
MAP.put(IMPL_TYPE_ALIAS_NOT_TO_CLASS, "Right-hand side of 'impl' type alias should be a class, not another type alias");
@@ -272,7 +274,7 @@ public class DefaultErrorMessages {
MAP.put(IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE, "Right-hand side of 'impl' type alias cannot contain use-site variance or star projections");
MAP.put(IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION, "Type arguments in the right-hand side of 'impl' type alias should be its type parameters in the same order, e.g. 'impl typealias Foo<A, B> = Bar<A, B>'");
MAP.put(HEADER_WITHOUT_IMPLEMENTATION, "Header declaration ''{0}'' has no implementation in module {1}{2}", NAME,
MAP.put(HEADER_WITHOUT_IMPLEMENTATION, "Header declaration ''{0}'' has no implementation in module{1}{2}", NAME,
PLATFORM, PlatformIncompatibilityDiagnosticRenderer.INSTANCE);
MAP.put(IMPLEMENTATION_WITHOUT_HEADER, "Modifier 'impl' is only applicable to members that are initially declared in platform-independent code");
@@ -368,6 +370,7 @@ public class DefaultErrorMessages {
MAP.put(DELEGATION_IN_INTERFACE, "Interfaces cannot use delegation");
MAP.put(DELEGATION_NOT_TO_INTERFACE, "Only interfaces can be delegated to");
MAP.put(DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE, "Delegated member ''{0}'' hides supertype override: {1}. Please specify proper override explicitly", COMPACT, commaSeparated(SHORT_NAMES_IN_TYPES));
MAP.put(NO_CONSTRUCTOR, "This class does not have a constructor");
MAP.put(RESOLUTION_TO_CLASSIFIER, "{2}", NAME, TO_STRING, STRING);
MAP.put(NOT_A_CLASS, "Not a class");

View File

@@ -76,7 +76,7 @@ object Renderers {
@JvmField val NAME = Renderer<Named> { it.name.asString() }
@JvmField val PLATFORM = Renderer<ModuleDescriptor> {
if (it.platformKind == PlatformKind.DEFAULT) "" else "for " + it.platformKind.name
if (it.platformKind == PlatformKind.DEFAULT) "" else " for " + it.platformKind.name
}
@JvmField val VISIBILITY = Renderer<Visibility> {

View File

@@ -41,19 +41,26 @@ interface AnnotationBasedExtension {
private fun AnnotationDescriptor.isASpecialAnnotation(
modifierListOwner: KtModifierListOwner?,
visitedAnnotations: MutableSet<String> = hashSetOf(),
allowMetaAnnotations: Boolean = true
): Boolean {
val annotationType = type.constructor.declarationDescriptor ?: return false
if (annotationType.fqNameSafe.asString() in getAnnotationFqNames(modifierListOwner)) return true
val annotationFqName = annotationType.fqNameSafe.asString()
if (annotationFqName in visitedAnnotations) return false // Prevent infinite recursion
if (annotationFqName in getAnnotationFqNames(modifierListOwner)) return true
visitedAnnotations.add(annotationFqName)
if (allowMetaAnnotations) {
for (metaAnnotation in annotationType.annotations) {
if (metaAnnotation.isASpecialAnnotation(modifierListOwner, allowMetaAnnotations = false)) {
if (metaAnnotation.isASpecialAnnotation(modifierListOwner, visitedAnnotations, allowMetaAnnotations = true)) {
return true
}
}
}
visitedAnnotations.remove(annotationFqName)
return false
}
}

View File

@@ -17,14 +17,11 @@
package org.jetbrains.kotlin.resolve.annotations
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ErrorValue
import org.jetbrains.kotlin.resolve.inline.InlineUtil
private val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
@@ -54,17 +51,3 @@ fun AnnotationDescriptor.argumentValue(parameterName: String): Any? {
return constant.value
}
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
fun MemberDescriptor.isInlineOnlyOrReified(): Boolean {
if (this !is FunctionDescriptor) return false
return typeParameters.any { it.isReified } || hasInlineOnlyAnnotation()
}
fun MemberDescriptor.hasInlineOnlyAnnotation(): Boolean {
if (this !is FunctionDescriptor) return false
return annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME) && InlineUtil.isInline(this).apply {
assert(this) { "Function is not inline: ${this@hasInlineOnlyAnnotation}"; }
}
}

View File

@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers
@@ -274,6 +273,10 @@ class DeclarationsChecker(
trace.report(HEADER_DECLARATION_WITH_BODY.on(declaration))
}
if (constructorDescriptor.containingDeclaration.kind == ClassKind.ENUM_CLASS) {
trace.report(HEADER_ENUM_CONSTRUCTOR.on(declaration))
}
if (declaration is KtPrimaryConstructor && !DescriptorUtils.isAnnotationClass(constructorDescriptor.constructedClass)) {
for (parameter in declaration.valueParameters) {
if (parameter.hasValOrVar()) {
@@ -895,15 +898,20 @@ class DeclarationsChecker(
}
}
private fun checkEnumEntry(enumEntry: KtEnumEntry, classDescriptor: ClassDescriptor) {
val declaration = classDescriptor.containingDeclaration
if (DescriptorUtils.isEnumClass(declaration)) {
if (!enumEntry.hasInitializer() && !hasDefaultConstructor(declaration as ClassDescriptor)) {
private fun checkEnumEntry(enumEntry: KtEnumEntry, enumEntryClass: ClassDescriptor) {
val enumClass = enumEntryClass.containingDeclaration as ClassDescriptor
if (DescriptorUtils.isEnumClass(enumClass)) {
if (enumClass.isHeader) {
if (enumEntry.getBody() != null) {
trace.report(HEADER_ENUM_ENTRY_WITH_BODY.on(enumEntry))
}
}
else if (!enumEntry.hasInitializer() && !hasDefaultConstructor(enumClass)) {
trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry))
}
}
else {
assert(DescriptorUtils.isInterface(declaration)) { "Enum entry should be declared in enum class: " + classDescriptor }
assert(DescriptorUtils.isInterface(enumClass)) { "Enum entry should be declared in enum class: " + enumEntryClass }
}
}

View File

@@ -1141,7 +1141,7 @@ public class DescriptorResolver {
/* lateInit = */ false,
/* isConst = */ false,
/* isHeader = */ false,
/* isImpl = */ false,
/* isImpl = */ modifierList != null && modifierList.hasModifier(KtTokens.IMPL_KEYWORD),
/* isExternal = */ false
);
propertyWrapper.setDescriptor(propertyDescriptor);

View File

@@ -73,7 +73,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
InfixModifierChecker(),
SinceKotlinAnnotationValueChecker,
ReifiedTypeParameterAnnotationChecker(),
DynamicReceiverChecker
DynamicReceiverChecker,
DelegationChecker()
)
private val DEFAULT_CALL_CHECKERS = listOf(

View File

@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.lexer.KtToken;
@@ -51,13 +50,13 @@ import static org.jetbrains.kotlin.resolve.inline.InlineUtil.checkNonLocalReturn
class InlineChecker implements CallChecker {
private final FunctionDescriptor descriptor;
private final Set<CallableDescriptor> inlinableParameters = new LinkedHashSet<CallableDescriptor>();
private final boolean isEffectivelyPublicOrPublishedApiFunction;
private final EffectiveVisibility inlineFunEffectiveVisibility;
private final boolean isEffectivelyPrivateApiFunction;
public InlineChecker(@NotNull FunctionDescriptor descriptor) {
assert InlineUtil.isInline(descriptor) : "This extension should be created only for inline functions: " + descriptor;
this.descriptor = descriptor;
this.isEffectivelyPublicOrPublishedApiFunction = isEffectivelyPublicOrPublishedApi(descriptor);
this.inlineFunEffectiveVisibility = EffectiveVisibilityKt.effectiveVisibility(descriptor, descriptor.getVisibility(), true);
this.isEffectivelyPrivateApiFunction = DescriptorUtilsKt.isEffectivelyPrivateApi(descriptor);
for (ValueParameterDescriptor param : descriptor.getValueParameters()) {
if (isInlinableParameter(param)) {
@@ -239,31 +238,33 @@ class InlineChecker implements CallChecker {
}
private void checkVisibilityAndAccess(
@NotNull CallableDescriptor declarationDescriptor,
@NotNull CallableDescriptor calledDescriptor,
@NotNull KtElement expression,
@NotNull CallCheckerContext context
) {
boolean declarationDescriptorIsPublicOrPublishedApi = isEffectivelyPublicOrPublishedApi(declarationDescriptor) ||
isDefinedInInlineFunction(declarationDescriptor);
if (isEffectivelyPublicOrPublishedApiFunction &&
!declarationDescriptorIsPublicOrPublishedApi &&
declarationDescriptor.getVisibility() != Visibilities.LOCAL) {
context.getTrace().report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor));
EffectiveVisibility calledFunEffectiveVisibility =
isDefinedInInlineFunction(calledDescriptor) ?
EffectiveVisibility.Public.INSTANCE :
EffectiveVisibilityKt.effectiveVisibility(calledDescriptor, calledDescriptor.getVisibility(), true);
boolean isCalledFunPublicOrPublishedApi = calledFunEffectiveVisibility.getPublicApi();
boolean isInlineFunPublicOrPublishedApi = inlineFunEffectiveVisibility.getPublicApi();
if (isInlineFunPublicOrPublishedApi &&
!isCalledFunPublicOrPublishedApi &&
calledDescriptor.getVisibility() != Visibilities.LOCAL) {
context.getTrace().report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor, descriptor));
}
else {
checkPrivateClassMemberAccess(declarationDescriptor, expression, context);
checkPrivateClassMemberAccess(calledDescriptor, expression, context);
}
if (isEffectivelyPublicOrPublishedApiFunction && declarationDescriptor.getVisibility() == Visibilities.PROTECTED) {
context.getTrace().report(Errors.PROTECTED_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor));
if (isInlineFunPublicOrPublishedApi &&
inlineFunEffectiveVisibility.toVisibility() != Visibilities.PROTECTED &&
calledFunEffectiveVisibility.toVisibility() == Visibilities.PROTECTED) {
context.getTrace().report(Errors.PROTECTED_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor));
}
}
private static boolean isEffectivelyPublicOrPublishedApi(@NotNull CallableDescriptor descriptor) {
EffectiveVisibility visibility = EffectiveVisibilityKt.effectiveVisibility(descriptor, descriptor.getVisibility(), true);
return visibility.getPublicApi();
}
private void checkPrivateClassMemberAccess(
@NotNull DeclarationDescriptor declarationDescriptor,
@NotNull KtElement expression,

View File

@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.hasRestrictsSuspendExtensionsAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.hasRestrictsSuspensionAnnotation
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
@@ -67,7 +67,7 @@ object CoroutineSuspendCallChecker : CallChecker {
// Here we only record enclosing function mapping (for backends purposes)
context.trace.record(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.call, enclosingSuspendFunction)
checkRestrictsSuspendExtensions(enclosingSuspendFunction, resolvedCall, reportOn, context)
checkRestrictsSuspension(enclosingSuspendFunction, resolvedCall, reportOn, context)
}
closestSuspensionLambdaDescriptor != null -> {
val callElement = resolvedCall.call.callElement as KtExpression
@@ -80,7 +80,7 @@ object CoroutineSuspendCallChecker : CallChecker {
BindingContext.ENCLOSING_SUSPEND_LAMBDA_FOR_SUSPENSION_POINT, resolvedCall.call, closestSuspensionLambdaDescriptor
)
checkRestrictsSuspendExtensions(closestSuspensionLambdaDescriptor, resolvedCall, reportOn, context)
checkRestrictsSuspension(closestSuspensionLambdaDescriptor, resolvedCall, reportOn, context)
}
else -> {
context.trace.report(Errors.ILLEGAL_SUSPEND_FUNCTION_CALL.on(reportOn))
@@ -110,7 +110,7 @@ fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, dia
}
}
private fun checkRestrictsSuspendExtensions(
private fun checkRestrictsSuspension(
enclosingCallableDescriptor: CallableDescriptor,
resolvedCall: ResolvedCall<*>,
reportOn: PsiElement,
@@ -118,8 +118,8 @@ private fun checkRestrictsSuspendExtensions(
) {
val enclosingSuspendReceiverValue = enclosingCallableDescriptor.extensionReceiverParameter?.value ?: return
fun ReceiverValue.isRestrictsSuspendExtensionsReceiver() = (type.supertypes() + type).any {
it.constructor.declarationDescriptor?.hasRestrictsSuspendExtensionsAnnotation() == true
fun ReceiverValue.isRestrictsSuspensionReceiver() = (type.supertypes() + type).any {
it.constructor.declarationDescriptor?.hasRestrictsSuspensionAnnotation() == true
}
infix fun ReceiverValue.sameInstance(other: ReceiverValue?): Boolean {
@@ -134,13 +134,13 @@ private fun checkRestrictsSuspendExtensions(
return this === (referenceTarget as? CallableDescriptor)?.extensionReceiverParameter?.value
}
if (!enclosingSuspendReceiverValue.isRestrictsSuspendExtensionsReceiver()) return
if (!enclosingSuspendReceiverValue.isRestrictsSuspensionReceiver()) return
// member of suspend receiver
if (enclosingSuspendReceiverValue sameInstance resolvedCall.dispatchReceiver) return
if (enclosingSuspendReceiverValue sameInstance resolvedCall.extensionReceiver &&
resolvedCall.candidateDescriptor.extensionReceiverParameter!!.value.isRestrictsSuspendExtensionsReceiver()) return
resolvedCall.candidateDescriptor.extensionReceiverParameter!!.value.isRestrictsSuspensionReceiver()) return
context.trace.report(Errors.ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL.on(reportOn))
}
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2010-2016 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.resolve.checkers
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.MemberComparator
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
class DelegationChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor !is ClassDescriptor) return
if (declaration !is KtClassOrObject) return
val delegationDescriptors = descriptor.defaultType.memberScope.getContributedDescriptors().
filterIsInstance<CallableMemberDescriptor>().filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }.sortedWith(MemberComparator.INSTANCE)
for (specifier in declaration.superTypeListEntries) {
if (specifier is KtDelegatedSuperTypeEntry) {
val superType = specifier.typeReference?.let { bindingContext.get(BindingContext.TYPE, it) } ?: continue
val superTypeDescriptor = superType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
val delegates = getDelegates(delegationDescriptors, superTypeDescriptor)
delegates.forEach { (delegated, delegatedTo) ->
checkDescriptor(declaration, delegated, delegatedTo, diagnosticHolder)
}
}
}
}
private fun checkDescriptor(
classDeclaration: KtDeclaration,
delegatedDescriptor: CallableMemberDescriptor,
delegatedToDescriptor: CallableMemberDescriptor,
diagnosticHolder: DiagnosticSink
) {
val reachableFromDelegated = findAllReachableDeclarations(delegatedDescriptor)
reachableFromDelegated.remove(delegatedDescriptor.original)
val toRemove = linkedSetOf<CallableMemberDescriptor>()
for (declaration in reachableFromDelegated) {
val reachable = findAllReachableDeclarations(declaration.original)
reachable.remove(declaration)
toRemove.addAll(reachable)
}
reachableFromDelegated.removeAll(toRemove)
reachableFromDelegated.remove(DescriptorUtils.unwrapFakeOverride(delegatedToDescriptor).original)
val nonAbstractReachable = reachableFromDelegated.filter { it.modality != Modality.ABSTRACT }
if (nonAbstractReachable.isNotEmpty()) {
/*In case of MANY_IMPL_MEMBER_NOT_IMPLEMENTED error there could be several elements otherwise only one*/
diagnosticHolder.report(DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE.on(classDeclaration, delegatedDescriptor, nonAbstractReachable.toList()))
}
}
fun getDelegates(
delegatedMethods: Iterable<CallableMemberDescriptor>,
toInterface: ClassDescriptor
): Map<CallableMemberDescriptor, CallableMemberDescriptor> {
return delegatedMethods
.keysToMapExceptNulls { delegatingMember ->
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
.filter { it.containingDeclaration == toInterface }
.map { overriddenDescriptor ->
val scope = toInterface.defaultType.memberScope
val name = overriddenDescriptor.name
// this is the actual member of delegateExpressionType that we are delegating to
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
.firstOrNull { it == overriddenDescriptor || OverridingUtil.overrides(it, overriddenDescriptor) }
}
actualDelegates.firstOrNull() as? CallableMemberDescriptor
}
}
}
private fun findAllReachableDeclarations(memberDescriptor: CallableMemberDescriptor): MutableSet<CallableMemberDescriptor> {
val collector = object : DFS.NodeHandlerWithListResult<CallableMemberDescriptor, CallableMemberDescriptor>() {
override fun afterChildren(current: CallableMemberDescriptor) {
if (current.kind.isReal) {
result.add(current.original)
}
}
}
DFS.dfs(listOf(memberDescriptor), { it.overriddenDescriptors }, collector)
return java.util.HashSet(collector.result())
}

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
@@ -28,9 +29,10 @@ import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Compatible
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Incompatible
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -55,11 +57,11 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
if (descriptor !is MemberDescriptor) return
val checkImpl = !languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformDoNotCheckImpl)
if (descriptor.isHeader && declaration.hasModifier(KtTokens.HEADER_KEYWORD)) {
val checkImpl = !languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformDoNotCheckImpl)
checkHeaderDeclarationHasImplementation(declaration, descriptor, diagnosticHolder, checkImpl)
}
else if (descriptor.isImpl && declaration.hasModifier(KtTokens.IMPL_KEYWORD)) {
else if (checkImpl && descriptor.isImpl && declaration.hasModifier(KtTokens.IMPL_KEYWORD)) {
checkImplementationHasHeaderDeclaration(declaration, descriptor, diagnosticHolder)
}
}
@@ -100,7 +102,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
private fun checkImplementationHasHeaderDeclaration(
reportOn: KtDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink
) {
fun ClassifierDescriptor.findDeclarationForClass(): ClassDescriptor? =
fun ClassifierDescriptorWithTypeParameters.findDeclarationForClass(): ClassDescriptor? =
findClassifiersFromTheSameModule().firstOrNull { declaration ->
this != declaration &&
declaration is ClassDescriptor && declaration.isHeader &&
@@ -121,7 +123,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
areCompatibleCallables(declaration, descriptor, checkImpl = false) == Compatible
}
}
is ClassifierDescriptor -> descriptor.findDeclarationForClass() != null
is ClassifierDescriptorWithTypeParameters -> descriptor.findDeclarationForClass() != null
else -> false
}
@@ -140,17 +142,29 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
is FunctionDescriptor -> scope.getContributedFunctions(name, NoLookupLocation.FOR_ALREADY_TRACKED)
is PropertyDescriptor -> scope.getContributedVariables(name, NoLookupLocation.FOR_ALREADY_TRACKED)
else -> throw AssertionError("Unsupported declaration: $this")
}.filter {
it.module == myModule // TODO: only obtain descriptors from our module to start with
}
} // TODO: only obtain descriptors from our module to start with
}
fun ClassifierDescriptor.findClassifiersFromTheSameModule(): Collection<ClassifierDescriptor> {
fun ClassifierDescriptorWithTypeParameters.findClassifiersFromTheSameModule(): Collection<ClassifierDescriptorWithTypeParameters> {
val myModule = moduleToCheck ?: module
// TODO: support nested classes
return myModule.getPackage(fqNameSafe.parent()).memberScope
.getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name }
.filterIsInstance<ClassifierDescriptor>()
val classId = classId ?: return emptyList()
fun MemberScope.getAllClassifiers(name: Name): Collection<ClassifierDescriptorWithTypeParameters> =
getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name }
.filterIsInstance<ClassifierDescriptorWithTypeParameters>()
val segments = classId.relativeClassName.pathSegments()
var classifiers = myModule.getPackage(classId.packageFqName).memberScope.getAllClassifiers(segments.first())
for (name in segments.subList(1, segments.size)) {
classifiers = classifiers.mapNotNull { classifier ->
(classifier as? ClassDescriptor)?.unsubstitutedInnerClassesScope?.getContributedClassifier(
name, NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassifierDescriptorWithTypeParameters
}
}
return classifiers
}
sealed class Compatibility {
@@ -177,7 +191,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
// Functions
object FunctionModifiers : Incompatible("modifiers are different (external, infix, inline, operator, suspend, tailrec)")
object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)")
object FunctionModifiersNotSubset : Incompatible("some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec)")
// Properties
@@ -188,7 +203,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
object ClassKind : Incompatible("class kinds are different (class, interface, object, enum, annotation)")
object ClassModifiers : Incompatible("modifiers are different (data)")
object ClassModifiers : Incompatible("modifiers are different (companion, inner)")
object Supertypes : Incompatible("some supertypes are missing in the implementation")
@@ -196,6 +211,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
unimplemented: List<Pair<CallableMemberDescriptor, Map<Incompatible, Collection<CallableMemberDescriptor>>>>
) : Incompatible("some members are not implemented", unimplemented)
object EnumEntries : Incompatible("some entries from header enum are missing in the impl enum")
// Common
object Modality : Incompatible("modality is different")
@@ -260,7 +277,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
else -> throw AssertionError("Unsupported declarations: $a, $b")
}
if (checkImpl && !b.isImpl) return Incompatible.NoImpl
if (checkImpl && !b.isImpl && b.kind == CallableMemberDescriptor.Kind.DECLARATION) return Incompatible.NoImpl
return Compatible
}
@@ -274,9 +291,13 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
}
private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): Compatibility {
if (!equalBy(a, b) { f ->
listOf(f.isExternal, f.isInfix, f.isInline, f.isOperator, f.isSuspend, f.isTailrec)
}) return Incompatible.FunctionModifiers
if (!equalBy(a, b) { f -> f.isSuspend }) return Incompatible.FunctionModifiersDifferent
if (a.isExternal && !b.isExternal ||
a.isInfix && !b.isInfix ||
a.isInline && !b.isInline ||
a.isOperator && !b.isOperator ||
a.isTailrec && !b.isTailrec) return Incompatible.FunctionModifiersNotSubset
return Compatible
}
@@ -314,20 +335,25 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
if (a.kind != b.kind) return Incompatible.ClassKind
if (!equalBy(a, b) { listOf(it.isCompanionObject, it.isInner) }) return Incompatible.ClassModifiers
val aTypeParams = a.declaredTypeParameters
val bTypeParams = b.declaredTypeParameters
if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount
val substitutor = Substitutor(aTypeParams, bTypeParams, parentSubstitutor)
if (a.modality != b.modality) return Incompatible.Modality
if (a.modality != b.modality && !(a.modality == Modality.FINAL && b.modality == Modality.OPEN)) return Incompatible.Modality
if (a.visibility != b.visibility) return Incompatible.Visibility
areCompatibleTypeParameters(aTypeParams, bTypeParams, substitutor).let { if (it != Compatible) return it }
if (!equalBy(a, b) { it.isData }) return Incompatible.ClassModifiers
if (!b.typeConstructor.supertypes.containsAll(a.typeConstructor.supertypes.map(substitutor))) return Incompatible.Supertypes
// Subtract kotlin.Any from supertypes because it's implicitly added if no explicit supertype is specified,
// and not added if an explicit supertype _is_ specified
val aSupertypes = a.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny)
val bSupertypes = b.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny)
if (!bSupertypes.containsAll(aSupertypes.map(substitutor))) return Incompatible.Supertypes
areCompatibleClassScopes(a, b, checkImpl && !implTypealias, substitutor).let { if (it != Compatible) return it }
@@ -365,7 +391,16 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
unimplemented.add(aMember to incompatibilityMap)
}
// TODO: check static scope, enum entries
if (a.kind == ClassKind.ENUM_CLASS) {
fun ClassDescriptor.enumEntries() =
unsubstitutedMemberScope.getDescriptorsFiltered().filter(DescriptorUtils::isEnumEntry).map { it.name }
val aEntries = a.enumEntries()
val bEntries = b.enumEntries()
if (!bEntries.containsAll(aEntries)) return Incompatible.EnumEntries
}
// TODO: check static scope?
if (unimplemented.isEmpty()) return Compatible

View File

@@ -17,13 +17,13 @@
package org.jetbrains.kotlin.resolve.inline
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.isInlineOnlyOrReified
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.AnalyzerExtensions
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.annotations.isInlineOnlyOrReified
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
object InlineAnalyzerExtension : AnalyzerExtensions.AnalyzerExtension {

View File

@@ -334,7 +334,13 @@ open class LazyClassMemberScope(
val classOrObject = declarationProvider.correspondingClassOrObject ?: return null
val hasPrimaryConstructor = classOrObject.hasExplicitPrimaryConstructor()
if (DescriptorUtils.isInterface(thisDescriptor) && !hasPrimaryConstructor) return null
if (!hasPrimaryConstructor) {
when (thisDescriptor.kind) {
ClassKind.INTERFACE -> return null
ClassKind.OBJECT, ClassKind.ENUM_CLASS -> if (thisDescriptor.isHeader) return null
else -> {}
}
}
if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) {
val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor(
@@ -343,11 +349,10 @@ open class LazyClassMemberScope(
setDeferredReturnType(constructor)
return constructor
}
else {
val constructor = DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace)
setDeferredReturnType(constructor)
return constructor
}
val constructor = DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace)
setDeferredReturnType(constructor)
return constructor
}
private fun resolveSecondaryConstructors(): Collection<ClassConstructorDescriptor> {

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/testData" type="java-test-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="intellij-core" level="project" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
<orderEntry type="module" module-name="build-common" />
<orderEntry type="module" module-name="cli" />
<orderEntry type="module" module-name="descriptor.loader.java" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="util" />
<orderEntry type="library" name="junit-4.12" level="project" />
</component>
</module>

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2010-2016 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.annotation
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
/**
* Annotation file is generated by collecting annotated elements of generated files.
* When compiling incrementally, the compiler generates only subset of all classes,
* so after compilation annotation file contains only a subset of annotated elements,
* which breaks the build.
*
* The workaround is to:
* 1. backup old file before incremental compilation;
* 2. after each iteration of IC:
* 2.1 remove classes corresponding to dirty source files
* 2.2 add annotations from newly generated annotations file
*/
interface AnnotationFileUpdater {
fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>)
fun revert()
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2010-2016 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
import java.io.File
sealed class ChangedFiles {
class Known(val modified: List<File>, val removed: List<File>) : ChangedFiles()
class Unknown : ChangedFiles()
}

View File

@@ -16,22 +16,19 @@
package org.jetbrains.kotlin.incremental
import org.gradle.api.logging.Logging
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.com.intellij.lang.java.JavaLanguage
import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.com.intellij.psi.PsiClass
import org.jetbrains.kotlin.com.intellij.psi.PsiFile
import org.jetbrains.kotlin.com.intellij.psi.PsiFileFactory
import org.jetbrains.kotlin.com.intellij.psi.PsiJavaFile
import com.intellij.lang.java.JavaLanguage
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.PsiJavaFile
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import java.io.File
import java.util.*
internal class ChangedJavaFilesProcessor {
private val log = Logging.getLogger(this.javaClass.simpleName)
internal class ChangedJavaFilesProcessor(private val reporter: ICReporter) {
private val allSymbols = HashSet<LookupSymbol>()
private val javaLang = JavaLanguage.INSTANCE
private val psiFileFactory: PsiFileFactory by lazy {
@@ -50,7 +47,7 @@ internal class ChangedJavaFilesProcessor {
val removedJava = filesDiff.removed.filter(File::isJavaFile)
if (removedJava.any()) {
log.kotlinDebug { "Some java files are removed: [${removedJava.joinToString()}]" }
reporter.report { "Some java files are removed: [${removedJava.joinToString()}]" }
return ChangesEither.Unknown()
}
@@ -60,7 +57,7 @@ internal class ChangedJavaFilesProcessor {
val psiFile = javaFile.psiFile()
if (psiFile !is PsiJavaFile) {
log.kotlinDebug { "Expected PsiJavaFile, got ${psiFile?.javaClass}" }
reporter.report { "Expected PsiJavaFile, got ${psiFile?.javaClass}" }
return ChangesEither.Unknown()
}

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.build.GeneratedJvmClass
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
@@ -25,15 +24,18 @@ import org.jetbrains.kotlin.incremental.storage.StringCollectionExternalizer
import org.jetbrains.kotlin.modules.TargetId
import java.io.File
internal class GradleIncrementalCacheImpl(targetDataRoot: File, targetOutputDir: File?, target: TargetId) : IncrementalCacheImpl<TargetId>(targetDataRoot, targetOutputDir, target) {
class GradleIncrementalCacheImpl(
targetDataRoot: File,
targetOutputDir: File?,
target: TargetId,
private val reporter: ICReporter
) : IncrementalCacheImpl<TargetId>(targetDataRoot, targetOutputDir, target) {
companion object {
private val SOURCES_TO_CLASSFILES = "sources-to-classfiles"
private val GENERATED_SOURCE_SNAPSHOTS = "generated-source-snapshot"
private val SOURCE_SNAPSHOTS = "source-snapshot"
}
private val log = org.gradle.api.logging.Logging.getLogger(this.javaClass)
internal val sourceToClassfilesMap = registerMap(SourceToClassfilesMap(SOURCES_TO_CLASSFILES.storageFile))
internal val generatedSourceSnapshotMap = registerMap(FileSnapshotMap(GENERATED_SOURCE_SNAPSHOTS.storageFile))
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile))
@@ -60,7 +62,7 @@ internal class GradleIncrementalCacheImpl(targetDataRoot: File, targetOutputDir:
// TODO: do it in the code that uses cache, since cache should not generally delete anything outside of it!
// but for a moment it is an easiest solution to implement
get(file).forEach {
log.kotlinDebug { "Deleting $it on clearing cache for $file" }
reporter.report { "Deleting $it on clearing cache for $file" }
it.delete()
}
storage.remove(file.absolutePath)

View File

@@ -19,10 +19,11 @@ package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.modules.TargetId
import java.io.File
internal class IncrementalCachesManager (
class IncrementalCachesManager (
private val targetId: TargetId,
private val cacheDirectory: File,
private val outputDir: File
private val outputDir: File,
private val reporter: ICReporter
) {
private val incrementalCacheDir = File(cacheDirectory, "increCache.${targetId.name}")
private val lookupCacheDir = File(cacheDirectory, "lookups")
@@ -32,7 +33,8 @@ internal class IncrementalCachesManager (
val incrementalCache: GradleIncrementalCacheImpl
get() {
if (incrementalCacheField == null) {
incrementalCacheField = GradleIncrementalCacheImpl(targetDataRoot = incrementalCacheDir.apply { mkdirs() }, targetOutputDir = outputDir, target = targetId)
val targetDataRoot = incrementalCacheDir.apply { mkdirs() }
incrementalCacheField = GradleIncrementalCacheImpl(targetDataRoot, outputDir, targetId, reporter)
}
return incrementalCacheField!!

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.annotation.SourceAnnotationsRegistry
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.GeneratedJvmClass
import org.jetbrains.kotlin.cli.common.ExitCode
@@ -27,43 +26,39 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.com.intellij.util.io.PersistentEnumeratorBase
import com.intellij.util.io.PersistentEnumeratorBase
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifference
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import java.io.EOFException
import java.io.File
import java.io.IOException
import java.util.*
internal fun makeIncrementally(
fun makeIncrementally(
cachesDir: File,
sourceRoots: Iterable<File>,
args: K2JVMCompilerArguments,
messageCollector: MessageCollector = MessageCollector.NONE,
reporter: IncReporter = EmptyIncReporter
reporter: ICReporter = EmptyICReporter
) {
val versions = listOf(normalCacheVersion(cachesDir),
experimentalCacheVersion(cachesDir),
dataContainerCacheVersion(cachesDir),
standaloneCacheVersion(cachesDir))
val versions = commonCacheVersions(cachesDir) + standaloneCacheVersion(cachesDir)
val kotlinExtensions = listOf("kt", "kts")
val allExtensions = kotlinExtensions + listOf("java")
val rootsWalk = sourceRoots.asSequence().map { it.walk() }.flatten()
val rootsWalk = sourceRoots.asSequence().flatMap { it.walk() }
val files = rootsWalk.filter(File::isFile)
val sourceFiles = files.filter { it.extension.toLowerCase() in allExtensions }.toList()
val kotlinFiles = sourceFiles.filter { it.extension.toLowerCase() in kotlinExtensions }
enableIC {
withIC {
val compiler = IncrementalJvmCompilerRunner(cachesDir, /* javaSourceRoots = */sourceRoots.toSet(), versions, reporter)
compiler.compile(kotlinFiles, args, messageCollector) {
it.incrementalCache.sourceSnapshotMap.compareAndUpdate(sourceFiles)
@@ -71,12 +66,12 @@ internal fun makeIncrementally(
}
}
private object EmptyIncReporter : IncReporter() {
private object EmptyICReporter : ICReporter() {
override fun report(message: ()->String) {
}
}
private inline fun enableIC(fn: ()->Unit) {
private inline fun withIC(fn: ()->Unit) {
val isEnabledBackup = IncrementalCompilation.isEnabled()
val isExperimentalBackup = IncrementalCompilation.isExperimental()
IncrementalCompilation.setIsEnabled(true)
@@ -91,15 +86,14 @@ private inline fun enableIC(fn: ()->Unit) {
}
}
internal class IncrementalJvmCompilerRunner(
class IncrementalJvmCompilerRunner(
workingDir: File,
private val javaSourceRoots: Set<File>,
private val cacheVersions: List<CacheVersion>,
private val reporter: IncReporter,
private val reporter: ICReporter,
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
private val sourceAnnotationsRegistry: SourceAnnotationsRegistry? = null,
private val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null,
private val artifactFile: File? = null
private val artifactChangesProvider: ArtifactChangesProvider? = null,
private val changesRegistry: ChangesRegistry? = null
) {
var anyClassesCompiled: Boolean = false
private set
@@ -114,22 +108,21 @@ internal class IncrementalJvmCompilerRunner(
getChangedFiles: (IncrementalCachesManager)->ChangedFiles
): ExitCode {
val targetId = TargetId(name = args.moduleName, type = "java-production")
var caches = IncrementalCachesManager(targetId, cacheDirectory, File(args.destination))
var caches = IncrementalCachesManager(targetId, cacheDirectory, File(args.destination), reporter)
fun onError(e: Exception): ExitCode {
caches.clean()
artifactDifferenceRegistryProvider?.clean()
// todo: warn?
reporter.report { "Possible cache corruption. Rebuilding. $e" }
// try to rebuild
val javaFilesProcessor = ChangedJavaFilesProcessor()
caches = IncrementalCachesManager(targetId, cacheDirectory, args.destinationAsFile)
val javaFilesProcessor = ChangedJavaFilesProcessor(reporter)
caches = IncrementalCachesManager(targetId, cacheDirectory, args.destinationAsFile, reporter)
return compileIncrementally(args, caches, javaFilesProcessor, allKotlinSources, targetId, CompilationMode.Rebuild, messageCollector)
}
return try {
val javaFilesProcessor = ChangedJavaFilesProcessor()
val javaFilesProcessor = ChangedJavaFilesProcessor(reporter)
val changedFiles = getChangedFiles(caches)
val compilationMode = calculateSourcesToCompile(javaFilesProcessor, caches, changedFiles, args)
compileIncrementally(args, caches, javaFilesProcessor, allKotlinSources, targetId, compilationMode, messageCollector)
@@ -141,9 +134,6 @@ internal class IncrementalJvmCompilerRunner(
onError(e)
}
finally {
artifactDifferenceRegistryProvider?.withRegistry(reporter) {
it.flush(memoryCachesOnly = true)
}
caches.close(flush = true)
reporter.report { "flushed incremental caches" }
}
@@ -233,10 +223,6 @@ internal class IncrementalJvmCompilerRunner(
reporter.report {"No classpath changes"}
return ChangesEither.Known()
}
if (artifactDifferenceRegistryProvider == null) {
reporter.report {"No artifact history provider"}
return ChangesEither.Unknown()
}
val lastBuildTS = lastBuildInfo?.startTS
if (lastBuildTS == null) {
@@ -247,23 +233,16 @@ internal class IncrementalJvmCompilerRunner(
val symbols = HashSet<LookupSymbol>()
val fqNames = HashSet<FqName>()
for (file in modifiedClasspath) {
val diffs = artifactDifferenceRegistryProvider.withRegistry(reporter) {artifactDifferenceRegistry ->
artifactDifferenceRegistry[file]
}
val diffs = artifactChangesProvider?.getChanges(file, lastBuildTS)
if (diffs == null) {
reporter.report {"Could not get changes for file: $file"}
return ChangesEither.Unknown()
}
val (beforeLastBuild, afterLastBuild) = diffs.partition {it.buildTS < lastBuildTS}
if (beforeLastBuild.isEmpty()) {
reporter.report {"No known build preceding timestamp $lastBuildTS for file $file"}
return ChangesEither.Unknown()
}
afterLastBuild.forEach {
symbols.addAll(it.dirtyData.dirtyLookupSymbols)
fqNames.addAll(it.dirtyData.dirtyClassesFqNames)
diffs.forEach {
symbols.addAll(it.dirtyLookupSymbols)
fqNames.addAll(it.dirtyClassesFqNames)
}
}
@@ -301,7 +280,6 @@ internal class IncrementalJvmCompilerRunner(
@Suppress("NAME_SHADOWING")
var compilationMode = compilationMode
reporter.report { "Artifact to register difference for: $artifactFile" }
val currentBuildInfo = BuildInfo(startTS = System.currentTimeMillis())
BuildInfo.write(currentBuildInfo, lastBuildInfoFile)
val buildDirtyLookupSymbols = HashSet<LookupSymbol>()
@@ -316,9 +294,6 @@ internal class IncrementalJvmCompilerRunner(
caches.incrementalCache.removeClassfilesBySources(dirtySources)
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
if (sourcesToCompile.isNotEmpty()) {
reporter.report { "compile iteration: ${reporter.pathsAsString(sourcesToCompile)}" }
}
// todo: more optimal to save only last iteration, but it will require adding standalone-ic specific logs
// (because jps rebuilds all files from last build if it failed and gradle rebuilds everything)
@@ -356,11 +331,6 @@ internal class IncrementalJvmCompilerRunner(
caches.lookupCache.update(lookupTracker, sourcesToCompile, removedKotlinSources)
if (compilationMode is CompilationMode.Rebuild) {
artifactFile?.let { artifactFile ->
artifactDifferenceRegistryProvider?.withRegistry(reporter) { registry ->
registry.remove(artifactFile)
}
}
break
}
@@ -380,21 +350,18 @@ internal class IncrementalJvmCompilerRunner(
if (exitCode == ExitCode.OK && compilationMode is CompilationMode.Incremental) {
buildDirtyLookupSymbols.addAll(javaFilesProcessor.allChangedSymbols)
}
if (artifactFile != null && artifactDifferenceRegistryProvider != null) {
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
val artifactDifference = ArtifactDifference(currentBuildInfo.startTS, dirtyData)
artifactDifferenceRegistryProvider.withRegistry(reporter) {registry ->
registry.add(artifactFile, artifactDifference)
if (changesRegistry != null) {
if (compilationMode is CompilationMode.Incremental) {
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
}
reporter.report {
val dirtySymbolsSorted = buildDirtyLookupSymbols.map { it.scope + "#" + it.name }.sorted()
"Added artifact difference for $artifactFile (ts: ${currentBuildInfo.startTS}): " +
"[\n\t${dirtySymbolsSorted.joinToString(",\n\t")}]"
else {
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode.javaClass}" }
changesRegistry.unknownChanges(currentBuildInfo.startTS)
}
}
if (exitCode == ExitCode.OK) {
sourceAnnotationsRegistry?.flush()
cacheVersions.forEach { it.saveIfNeeded() }
}
@@ -462,7 +429,6 @@ internal class IncrementalJvmCompilerRunner(
val outputItemCollector = OutputItemsCollectorImpl()
@Suppress("NAME_SHADOWING")
val messageCollector = MessageCollectorWrapper(messageCollector, outputItemCollector)
sourceAnnotationsRegistry?.clear()
try {
val incrementalCaches = makeIncrementalCachesMap(targets, { listOf<TargetId>() }, getIncrementalCache, { this })
@@ -473,7 +439,7 @@ internal class IncrementalJvmCompilerRunner(
reporter.report { "compiling with args: ${ArgumentUtils.convertArgumentsToStringList(args)}" }
reporter.report { "compiling with classpath: ${classpath.toList().sorted().joinToString()}" }
val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus, sourceAnnotationsRegistry)
val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus)
val exitCode = compiler.exec(messageCollector, compileServices, args)
val generatedFiles = outputItemCollector.generatedFiles(targets, targets.first(), {sourcesToCompile}, {outputDir})
reporter.reportCompileIteration(sourcesToCompile, exitCode)
@@ -504,10 +470,10 @@ internal class IncrementalJvmCompilerRunner(
}
}
internal var K2JVMCompilerArguments.destinationAsFile: File
var K2JVMCompilerArguments.destinationAsFile: File
get() = File(destination)
set(value) { destination = value.path }
internal var K2JVMCompilerArguments.classpathAsList: List<File>
var K2JVMCompilerArguments.classpathAsList: List<File>
get() = classpath.split(File.pathSeparator).map(::File)
set(value) { classpath = value.joinToString(separator = File.pathSeparator, transform = { it.path }) }

View File

@@ -22,10 +22,18 @@ import java.io.File
internal const val STANDALONE_CACHE_VERSION = 0
internal const val STANDALONE_VERSION_FILE_NAME = "standalone-ic-format-version.txt"
internal fun standaloneCacheVersion(dataRoot: File): CacheVersion =
CacheVersion(ownVersion = STANDALONE_CACHE_VERSION,
versionFile = File(dataRoot, STANDALONE_VERSION_FILE_NAME),
fun standaloneCacheVersion(dataRoot: File): CacheVersion =
customCacheVersion(STANDALONE_CACHE_VERSION, STANDALONE_VERSION_FILE_NAME, dataRoot)
fun customCacheVersion(version: Int, fileName: String, dataRoot: File, forceEnable: Boolean = false): CacheVersion =
CacheVersion(ownVersion = version,
versionFile = File(dataRoot, fileName),
whenVersionChanged = CacheVersion.Action.REBUILD_ALL_KOTLIN,
whenTurnedOn = CacheVersion.Action.REBUILD_ALL_KOTLIN,
whenTurnedOff = CacheVersion.Action.REBUILD_ALL_KOTLIN,
isEnabled = { IncrementalCompilation.isExperimental() })
isEnabled = { IncrementalCompilation.isExperimental() || forceEnable })
fun commonCacheVersions(cachesDir: File): List<CacheVersion> =
listOf(normalCacheVersion(cachesDir),
experimentalCacheVersion(cachesDir),
dataContainerCacheVersion(cachesDir))

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2010-2016 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.multiproject
import org.jetbrains.kotlin.incremental.DirtyData
import java.io.File
interface ArtifactChangesProvider {
fun getChanges(artifact: File, sinceTS: Long): Iterable<DirtyData>?
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2010-2016 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.multiproject
import org.jetbrains.kotlin.incremental.DirtyData
interface ChangesRegistry {
fun registerChanges(timestamp: Long, dirtyData: DirtyData)
fun unknownChanges(timestamp: Long)
}

View File

@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental.snapshots
import java.io.File
import java.util.*
internal class FileSnapshot(
class FileSnapshot(
val file: File,
val length: Long,
val hash: ByteArray

View File

@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.incremental.snapshots
import org.jetbrains.kotlin.com.intellij.util.io.DataExternalizer
import com.intellij.util.io.DataExternalizer
import java.io.DataInput
import java.io.DataOutput
import java.io.File
internal object FileSnapshotExternalizer : DataExternalizer<FileSnapshot> {
object FileSnapshotExternalizer : DataExternalizer<FileSnapshot> {
override fun save(out: DataOutput, value: FileSnapshot) {
out.writeUTF(value.file.canonicalPath)
out.writeLong(value.length)

View File

@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
import java.io.File
import java.util.*
internal class FileSnapshotMap(storageFile: File) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer) {
class FileSnapshotMap(storageFile: File) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer) {
override fun dumpValue(value: FileSnapshot): String =
value.toString()

View File

@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.incremental.snapshots
import java.io.File
internal interface FileSnapshotProvider {
interface FileSnapshotProvider {
operator fun get(file: File): FileSnapshot
}
internal class SimpleFileSnapshotProviderImpl : FileSnapshotProvider {
class SimpleFileSnapshotProviderImpl : FileSnapshotProvider {
override fun get(file: File): FileSnapshot {
val length = file.length()
val hash = file.md5

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2010-2016 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
import com.intellij.openapi.util.io.FileUtil
import org.junit.After
import org.junit.Before
import java.io.File
import kotlin.properties.Delegates
abstract class TestWithWorkingDir {
protected var workingDir: File by Delegates.notNull()
private set
@Before
open fun setUp() {
workingDir = FileUtil.createTempDirectory(this.javaClass.simpleName, null)
}
@After
open fun tearDown() {
workingDir.deleteRecursively()
}
}

View File

@@ -1,7 +1,21 @@
package org.jetbrains.kotlin.gradle
/*
* Copyright 2010-2016 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
import org.jetbrains.kotlin.gradle.incremental.dumpBuildLog
import org.jetbrains.kotlin.gradle.incremental.parseTestBuildLog
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@@ -9,7 +23,7 @@ import org.junit.runners.Parameterized
import java.io.File
@RunWith(Parameterized::class)
class BuildLogParserParametrizedIT : BaseGradleIT() {
class BuildLogParserParametrizedTest {
@Parameterized.Parameter
@JvmField
@@ -40,7 +54,7 @@ class BuildLogParserParametrizedIT : BaseGradleIT() {
}
companion object {
private val TEST_ROOT = File(resourcesRootFile, "buildLogsParserData")
private val TEST_ROOT = File("compiler/incremental-compilation-impl/testData/buildLogsParserData")
private val LOG_FILE_NAME = "build.log"
private val EXPECTED_PARSED_LOG_FILE_NAME = "expected.txt"
@@ -49,7 +63,7 @@ class BuildLogParserParametrizedIT : BaseGradleIT() {
@JvmStatic
fun data(): List<Array<String>> {
val directories = TEST_ROOT.listFiles().filter { it.isDirectory }
return directories.map { arrayOf(it.name) }.toList()
return directories.map { arrayOf(it.name) }
}
}
}

View File

@@ -22,15 +22,14 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.com.intellij.util.containers.HashMap
import org.jetbrains.kotlin.gradle.incremental.parseTestBuildLog
import com.intellij.util.containers.HashMap
import org.junit.Assert.assertEquals
import org.jetbrains.kotlin.incremental.testingUtils.*
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.io.File
import java.util.*
import kotlin.test.assertEquals
@RunWith(Parameterized::class)
class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
@@ -104,7 +103,7 @@ class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
val rebuildExpectedToSucceed = buildLogSteps.last().compileSucceeded
val rebuildSucceeded = rebuildResult.exitCode == ExitCode.OK
assertEquals(rebuildExpectedToSucceed, rebuildSucceeded, "Rebuild exit code differs from incremental exit code")
assertEquals("Rebuild exit code differs from incremental exit code", rebuildExpectedToSucceed, rebuildSucceeded)
if (rebuildSucceeded) {
assertEqualDirectories(outDir, rebuildOutDir, forgiveExtraFiles = rebuildSucceeded)
@@ -125,7 +124,7 @@ class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
val compiledSources = arrayListOf<File>()
var resultExitCode = ExitCode.OK
val reporter = object : IncReporter() {
val reporter = object : ICReporter() {
override fun report(message: ()->String) {
}
@@ -185,7 +184,7 @@ class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
}
companion object {
private val jpsResourcesPath = File("../../../jps-plugin/testData/incremental")
private val jpsResourcesPath = File("jps-plugin/testData/incremental")
private val ignoredDirs = setOf(File(jpsResourcesPath, "cacheVersionChanged"),
File(jpsResourcesPath, "changeIncrementalOption"),
File(jpsResourcesPath, "custom"),

View File

@@ -1,6 +1,22 @@
package org.jetbrains.kotlin.gradle.incremental
/*
* Copyright 2010-2016 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.
*/
import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil
package org.jetbrains.kotlin.incremental
import com.intellij.openapi.util.io.FileUtil
import java.io.File
private const val BEGIN_COMPILED_FILES = "Compiling files:"
@@ -83,7 +99,7 @@ fun parseTestBuildLog(file: File): List<BuildStep> {
}
}
// used in integration tests
// used in gradle integration tests
@Suppress("unused")
fun dumpBuildLog(buildSteps: Iterable<BuildStep>): String {
val sb = StringBuilder()

View File

@@ -0,0 +1,50 @@
================ Step #1 =================
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/inline/InlineGetKt.class
End of files
Compiling files:
src/inlineGet.kt
End of files
Marked as dirty by Kotlin:
src/UsageVal.kt
src/UsageVar.kt
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Cleaning output files:
out/production/module/usage/UsageVal.class
out/production/module/usage/UsageVar.class
End of files
Compiling files:
src/UsageVal.kt
src/UsageVar.kt
End of files
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Exit code: NOTHING_DONE
------------------------------------------
================ Step #2 =================
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/inline/InlineSetKt.class
End of files
Compiling files:
src/inlineSet.kt
End of files
Marked as dirty by Kotlin:
src/UsageVar.kt
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Cleaning output files:
out/production/module/usage/UsageVar.class
End of files
Compiling files:
src/UsageVar.kt
End of files
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Exit code: NOTHING_DONE
------------------------------------------

View File

@@ -0,0 +1,16 @@
================ Step #1 =================
Compiling files:
src/UsageVal.kt
src/UsageVar.kt
src/inlineGet.kt
End of files
------------------------------------------
================ Step #2 =================
Compiling files:
src/UsageVar.kt
src/inlineSet.kt
End of files
------------------------------------------

View File

@@ -0,0 +1,37 @@
================ Step #1 =================
Cleaning output files:
out/production/module1/META-INF/module1.kotlin_module
out/production/module1/a/A.class
out/production/module1/a/ClassAnnotation.class
out/production/module1/a/FileAnnotation.class
out/production/module1/a/Module1_aKt.class
End of files
Compiling files:
module1/src/module1_a.kt
End of files
Marked as dirty by Kotlin:
module2/src/module2_b.kt
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Exit code: NOTHING_DONE
------------------------------------------
Cleaning output files:
out/production/module2/META-INF/module2.kotlin_module
out/production/module2/b/B.class
out/production/module2/b/Module2_bKt.class
End of files
Compiling files:
module2/src/module2_b.kt
End of files
Exit code: ABORT
------------------------------------------
COMPILATION FAILED
Cannot access 'FileAnnotation': it is internal in 'a'
Cannot access 'A': it is internal in 'a'
Cannot access 'FileAnnotation': it is internal in 'a'
Cannot access 'ClassAnnotation': it is internal in 'a'
Cannot access 'ClassAnnotation': it is internal in 'a'
Function effective visibility 'public' should be the same or less permissive than its parameter type effective visibility 'internal'
Cannot access 'A': it is internal in 'a'
Cannot access 'a': it is internal in 'a'

View File

@@ -0,0 +1,16 @@
================ Step #1 =================
Compiling files:
module1/src/module1_a.kt
module2/src/module2_b.kt
End of files
------------------------------------------
COMPILATION FAILED
Cannot access 'FileAnnotation': it is internal in 'a'
Cannot access 'A': it is internal in 'a'
Cannot access 'FileAnnotation': it is internal in 'a'
Cannot access 'ClassAnnotation': it is internal in 'a'
Cannot access 'ClassAnnotation': it is internal in 'a'
Function effective visibility 'public' should be the same or less permissive than its parameter type effective visibility 'internal'
Cannot access 'A': it is internal in 'a'
Cannot access 'a': it is internal in 'a'

View File

@@ -0,0 +1,17 @@
================ Step #1 =================
Cleaning output files:
out/production/module/JavaClass.class
out/production/module/META-INF/module.kotlin_module
out/production/module/UsageKt.class
End of files
Compiling files:
src/usage.kt
End of files
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Compiling files:
src/JavaClass.java
End of files
Exit code: NOTHING_DONE
------------------------------------------

View File

@@ -0,0 +1,7 @@
================ Step #1 =================
Compiling files:
src/usage.kt
src/JavaClass.java
End of files
------------------------------------------

View File

@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch
import org.jetbrains.kotlin.util.collectionUtils.getFirstClassifierDiscriminateHeaders
import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
import org.jetbrains.kotlin.utils.Printer
@@ -40,7 +40,7 @@ class LexicalChainedScope @JvmOverloads constructor(
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= getFromAllScopes(memberScopes) { it.getContributedDescriptors() }
override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstMatch(memberScopes) { it.getContributedClassifier(name, location) }
override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstClassifierDiscriminateHeaders(memberScopes) { it.getContributedClassifier(name, location) }
override fun getContributedVariables(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) }

View File

@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.resolve.scopes
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope
@@ -36,4 +38,14 @@ class SubpackagesImportingScope(
override fun getContributedVariables(name: Name, location: LookupLocation) = super.getContributedVariables(name, location)
override fun getContributedFunctions(name: Name, location: LookupLocation) = super.getContributedFunctions(name, location)
//TODO: kept old behavior, but it seems very strange (super call seems more applicable)
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
return ImportingScope.Empty.getContributedClassifier(name, location)
}
//TODO: kept old behavior, but it seems very strange (super call seems more applicable)
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
return ImportingScope.Empty.getContributedDescriptors(kindFilter, nameFilter)
}
}

View File

@@ -19,6 +19,6 @@ package-fragment kotlin.coroutines
public final inline suspend fun </*0*/ T> suspendCoroutineOrReturn(/*0*/ block: (kotlin.coroutines.Continuation<T>) -> kotlin.Any?): T
}
@kotlin.SinceKotlin(version = "1.1") @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class RestrictsSuspendExtensions : kotlin.Annotation {
/*primary*/ public constructor RestrictsSuspendExtensions()
@kotlin.SinceKotlin(version = "1.1") @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class RestrictsSuspension : kotlin.Annotation {
/*primary*/ public constructor RestrictsSuspension()
}

View File

@@ -0,0 +1,122 @@
// WITH_RUNTIME
// WITH_COROUTINES
// TARGET_BACKEND: JVM
import kotlin.coroutines.*
interface AsyncGenerator<in T> {
suspend fun yield(value: T)
}
interface AsyncSequence<out T> {
operator fun iterator(): AsyncIterator<T>
}
interface AsyncIterator<out T> {
operator suspend fun hasNext(): Boolean
operator suspend fun next(): T
}
fun <T> asyncGenerate(block: suspend AsyncGenerator<T>.() -> Unit): AsyncSequence<T> = object : AsyncSequence<T> {
override fun iterator(): AsyncIterator<T> {
val iterator = AsyncGeneratorIterator<T>()
iterator.nextStep = block.createCoroutine(receiver = iterator, completion = iterator)
return iterator
}
}
class AsyncGeneratorIterator<T>: AsyncIterator<T>, AsyncGenerator<T>, Continuation<Unit> {
var computedNext = false
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
// if (computesNext) computeContinuation is Continuation<T>
// if (!computesNext) computeContinuation is Continuation<Boolean>
var computesNext = false
var computeContinuation: Continuation<*>? = null
suspend fun computeHasNext(): Boolean = CoroutineIntrinsics.suspendCoroutineOrReturn { c ->
computesNext = false
computeContinuation = c
nextStep!!.resume(Unit)
CoroutineIntrinsics.SUSPENDED
}
suspend fun computeNext(): T = CoroutineIntrinsics.suspendCoroutineOrReturn { c ->
computesNext = true
computeContinuation = c
nextStep!!.resume(Unit)
CoroutineIntrinsics.SUSPENDED
}
@Suppress("UNCHECKED_CAST")
fun resumeIterator(exception: Throwable?) {
if (exception != null) {
done()
computeContinuation!!.resumeWithException(exception)
return
}
if (computesNext) {
computedNext = false
(computeContinuation as Continuation<T>).resume(nextValue as T)
} else {
(computeContinuation as Continuation<Boolean>).resume(nextStep != null)
}
}
override suspend fun hasNext(): Boolean {
if (!computedNext) return computeHasNext()
return nextStep != null
}
override suspend fun next(): T {
if (!computedNext) return computeNext()
computedNext = false
return nextValue as T
}
private fun done() {
computedNext = true
nextStep = null
}
// Completion continuation implementation
override fun resume(value: Unit) {
done()
resumeIterator(null)
}
override fun resumeWithException(exception: Throwable) {
done()
resumeIterator(exception)
}
// Generator implementation
override suspend fun yield(value: T): Unit = CoroutineIntrinsics.suspendCoroutineOrReturn { c ->
computedNext = true
nextValue = value
nextStep = c
resumeIterator(null)
CoroutineIntrinsics.SUSPENDED
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
val seq = asyncGenerate {
yield("O")
yield("K")
}
var res = ""
builder {
for (i in seq) {
res += i
}
}
return res
}

View File

@@ -0,0 +1,46 @@
// WITH_RUNTIME
// WITH_COROUTINES
import kotlin.coroutines.*
suspend fun suspendHere(): String = CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
x.resume("OK")
CoroutineIntrinsics.SUSPENDED
}
fun builder(c: suspend () -> Unit) {
var wasResumeCalled = false
c.startCoroutine(object : Continuation<Unit> {
override fun resume(value: Unit) {
wasResumeCalled = true
}
override fun resumeWithException(exception: Throwable) {
}
})
if (!wasResumeCalled) throw RuntimeException("fail 1")
}
fun box(): String {
var result = ""
builder {
run {
if (result == "") return@builder
}
suspendHere()
throw RuntimeException("fail 2")
}
result = "fail1"
builder {
run {
if (result == "") return@builder
}
result = suspendHere()
}
return result
}

View File

@@ -0,0 +1,42 @@
// WITH_RUNTIME
// WITH_COROUTINES
import kotlin.coroutines.*
suspend fun suspendHere(): String = CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
x.resume("OK")
CoroutineIntrinsics.SUSPENDED
}
fun builder(c: suspend () -> Unit) {
var wasResumeCalled = false
c.startCoroutine(object : Continuation<Unit> {
override fun resume(value: Unit) {
wasResumeCalled = true
}
override fun resumeWithException(exception: Throwable) {
}
})
if (!wasResumeCalled) throw RuntimeException("fail 1")
}
fun box(): String {
var result = ""
builder {
if (result == "") return@builder
suspendHere()
throw RuntimeException("fail 2")
}
result = "fail"
builder {
if (result == "") return@builder
result = suspendHere()
}
return result
}

View File

@@ -0,0 +1,34 @@
// WITH_RUNTIME
// WITH_COROUTINES
// IGNORE_BACKEND: JS
import kotlin.coroutines.*
var result = "0"
suspend fun suspendHere(x: Int): Unit {
run {
if (x == 0) return
if (x == 1) return@suspendHere
}
result = "OK"
return CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
x.resume(Unit)
CoroutineIntrinsics.SUSPENDED
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
builder {
if (suspendHere(0) != Unit) throw RuntimeException("fail 1")
if (suspendHere(1) != Unit) throw RuntimeException("fail 2")
if (suspendHere(2) != Unit) throw RuntimeException("fail 3")
}
return result
}

View File

@@ -0,0 +1,27 @@
// WITH_RUNTIME
// WITH_COROUTINES
import kotlin.coroutines.*
var result = "0"
suspend fun suspendHere(x: Int): Unit {
if (x == 0) return
result = "OK"
return CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
x.resume(Unit)
CoroutineIntrinsics.SUSPENDED
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
builder {
suspendHere(0)
suspendHere(1)
}
return result
}

View File

@@ -13,7 +13,7 @@ class ComparablePair<T : Comparable<T>>(val first: T, val second: T) : Comparabl
fun <T : Comparable<T>> genericRangeTo(start: T, endInclusive: T) = start..endInclusive
operator fun Double.rangeTo(other: Double) = genericRangeTo(this, other)
// some weird inverted range
operator fun Float.rangeTo(other: Float) = object : ClosedComparableRange<Float> {
operator fun Float.rangeTo(other: Float) = object : ClosedFloatingPointRange<Float> {
override val endInclusive: Float = this@rangeTo
override val start: Float = other
override fun lessThanOrEquals(a: Float, b: Float) = a >= b

View File

@@ -0,0 +1,23 @@
// IGNORE_BACKEND: JS
// WITH_REFLECT
import kotlin.reflect.*
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
inline fun <reified T> f() = 1
fun g() {}
class Foo {
inline fun <reified T> h(t: T) = 1
}
fun box(): String {
assertEquals(::g, ::g.javaMethod!!.kotlinFunction)
val h = Foo::class.members.single { it.name == "h" } as KFunction<*>
assertEquals(h, h.javaMethod!!.kotlinFunction)
return "OK"
}

View File

@@ -1,3 +1,4 @@
// WITH_RUNTIME
import kotlin.coroutines.*
class Controller {
suspend fun suspendHere() = CoroutineIntrinsics.suspendCoroutineOrReturn<String> { x ->

View File

@@ -21,4 +21,5 @@ fun box(): String {
// 1 GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
// 1 GETSTATIC EmptyContinuation.INSTANCE
// 2 GETSTATIC
// 1 GETSTATIC kotlin/coroutines/CoroutineIntrinsics.INSTANCE
// 3 GETSTATIC

View File

@@ -0,0 +1,65 @@
public interface AsyncGenerator {
public abstract @org.jetbrains.annotations.Nullable method yield(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
public final class AsyncGeneratorIterator {
private @org.jetbrains.annotations.Nullable field computeContinuation: kotlin.coroutines.Continuation
private field computedNext: boolean
private field computesNext: boolean
private @org.jetbrains.annotations.Nullable field nextStep: kotlin.coroutines.Continuation
private @org.jetbrains.annotations.Nullable field nextValue: java.lang.Object
public method <init>(): void
public final @org.jetbrains.annotations.Nullable method computeHasNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public final @org.jetbrains.annotations.Nullable method computeNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
private final method done(): void
public final @org.jetbrains.annotations.Nullable method getComputeContinuation(): kotlin.coroutines.Continuation
public final method getComputedNext(): boolean
public final method getComputesNext(): boolean
public final @org.jetbrains.annotations.Nullable method getNextStep(): kotlin.coroutines.Continuation
public final @org.jetbrains.annotations.Nullable method getNextValue(): java.lang.Object
public @org.jetbrains.annotations.Nullable method hasNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method next(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public method resume(@org.jetbrains.annotations.NotNull p0: kotlin.Unit): void
public synthetic method resume(p0: java.lang.Object): void
public final @kotlin.Suppress method resumeIterator(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
public final method setComputeContinuation(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
public final method setComputedNext(p0: boolean): void
public final method setComputesNext(p0: boolean): void
public final method setNextStep(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
public final method setNextValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
public @org.jetbrains.annotations.Nullable method yield(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
public interface AsyncIterator {
public abstract @org.jetbrains.annotations.Nullable method hasNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public abstract @org.jetbrains.annotations.Nullable method next(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
}
public final class AsyncIteratorKt {
public final static @org.jetbrains.annotations.NotNull method asyncGenerate(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): AsyncSequence
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
}
public interface AsyncSequence {
public abstract @org.jetbrains.annotations.NotNull method iterator(): AsyncIterator
}
public final class CoroutineUtilKt {
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
}
public final class EmptyContinuation {
public final static field INSTANCE: EmptyContinuation
private method <init>(): void
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
}

View File

@@ -0,0 +1,19 @@
public final class CoroutineNonLocalReturnKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
}
public final class CoroutineUtilKt {
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
}
public final class EmptyContinuation {
public final static field INSTANCE: EmptyContinuation
private method <init>(): void
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
}

View File

@@ -0,0 +1,19 @@
public final class CoroutineReturnKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
}
public final class CoroutineUtilKt {
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
}
public final class EmptyContinuation {
public final static field INSTANCE: EmptyContinuation
private method <init>(): void
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
}

View File

@@ -0,0 +1,22 @@
public final class CoroutineUtilKt {
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
}
public final class EmptyContinuation {
public final static field INSTANCE: EmptyContinuation
private method <init>(): void
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
}
public final class SuspendNonLocalReturnKt {
private static @org.jetbrains.annotations.NotNull field result: java.lang.String
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String
public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
public final static @org.jetbrains.annotations.Nullable method suspendHere(p0: int, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}

View File

@@ -0,0 +1,22 @@
public final class CoroutineUtilKt {
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
}
public final class EmptyContinuation {
public final static field INSTANCE: EmptyContinuation
private method <init>(): void
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
}
public final class SuspendReturnKt {
private static @org.jetbrains.annotations.NotNull field result: java.lang.String
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String
public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
public final static @org.jetbrains.annotations.Nullable method suspendHere(p0: int, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}

View File

@@ -15,5 +15,5 @@ public final class InComparableRangeKt {
public final static method check(p0: float, p1: float, p2: float): boolean
public final static @org.jetbrains.annotations.NotNull method genericRangeTo(@org.jetbrains.annotations.NotNull p0: java.lang.Comparable, @org.jetbrains.annotations.NotNull p1: java.lang.Comparable): kotlin.ranges.ClosedRange
public final static @org.jetbrains.annotations.NotNull method rangeTo(p0: double, p1: double): kotlin.ranges.ClosedRange
public final static @org.jetbrains.annotations.NotNull method rangeTo(p0: float, p1: float): kotlin.ranges.ClosedComparableRange
public final static @org.jetbrains.annotations.NotNull method rangeTo(p0: float, p1: float): kotlin.ranges.ClosedFloatingPointRange
}

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