Compare commits

..

615 Commits

Author SHA1 Message Date
Alexey Sedunov
11e9e7b552 Move: Fix ClassCastException on processing of callable references to Java methods
#KT-16809 Fixed
2017-03-22 00:07:17 +03:00
Alexey Sedunov
2f95131368 Move: Filter out ConflictUsageInfo instances before running the refactoring
#KT-16556 Fixed
2017-03-22 00:07:16 +03:00
Alexey Sedunov
d6599c8b83 Move: Fix NPE on moving directory where at least one Kotlin file contains package directive unmatched by the containing directory
#KT-8955 Fixed
2017-03-22 00:07:15 +03:00
Alexey Sedunov
048d1c0365 Move: Get element listener before original declaration is invalidated by the refactoring 2017-03-22 00:07:14 +03:00
Alexey Sedunov
cd1420f7c1 Move: Fix incorrect FqName when moving declaration to default package
#KT-15586 Fixed
2017-03-22 00:07:13 +03:00
Alexey Sedunov
4bcde41e8c Move: Avoid temporary file rename if the current name doesn't conflict with other files in the target directory. Improve protection against exceptions during the refactoring which may prevent final rename 2017-03-22 00:07:12 +03:00
Alexey Sedunov
6b6736fd55 Move: Do not report conflict on usages of inherited protected members
#KT-15190 Fixed
2017-03-22 00:07:11 +03:00
Alexey Sedunov
b67a77404e Move: Implement conflict checking for internal members
#KT-13190 Fixed
2017-03-22 00:07:10 +03:00
Alexey Sedunov
f186e9f11f Move: Fix processing of references to non-real (fake override, etc.) members of companion object
#KT-15559 Fixed
2017-03-22 00:07:09 +03:00
Alexey Sedunov
d774807204 Implement post-refactoring optimization of unused imports
#KT-15822 Fixed
 #KT-13755 Fixed
2017-03-22 00:07:08 +03:00
Alexey Sedunov
a4e35011e4 Move: Check that constructor call corresponds to class being moved before
transforming outer instance to argument (fixes tests broken after the
commit before)
2017-03-22 00:07:07 +03:00
Alexey Sedunov
d14f341187 Move: Exclude conflict-associated usages from refactoring. Move file internal usages search to MoveKotlinDeclarationsProcessor 2017-03-22 00:07:06 +03:00
Alexey Sedunov
6cbdb53433 Move: Use Kotlin declaration mover on KtFile because existing file mover
does not process conflicts
 #KT-13911 Fixed
2017-03-22 00:07:05 +03:00
Yan Zhulanow
7a5f94129c Add ClassBuilderMode.KAPT3 tests 2017-03-21 20:49:36 +03:00
Yan Zhulanow
e25e19c4d6 Refactoring: Remove light analysis test data
The light analysis test data is not needed anymore cause the light analysis result is now automatically checked against the one from the full analysis.
2017-03-21 20:49:36 +03:00
Yan Zhulanow
c50881fd02 Refactoring: Extract light analysis tests from box tests 2017-03-21 20:49:34 +03:00
Mikhail Glukhikh
23848fa728 Suggest bound references in "Lambda --> Reference" for 1.1+ only 2017-03-21 20:32:15 +03:00
Ilya Chernikov
0f21db1ecb Copy base script classes to script-runtime before building bootstrap 2017-03-21 16:30:51 +01:00
Ilya Chernikov
08f6b6c93c minor: get rid of the compiler-test dependency in source-sections test 2017-03-21 16:30:50 +01:00
Ilya Chernikov
1eab936618 minor: Bump rubygrapefruit native-platform version to 0.14 2017-03-21 16:30:49 +01:00
Ilya Chernikov
d439c13fb5 minor: correct measurement error in eval bench test 2017-03-21 16:30:48 +01:00
Ilya Chernikov
4043f491da minor: replace Pair with data class in daemon client connectAndLease call
backport from 1.0.7
2017-03-21 16:30:47 +01:00
Ilya Chernikov
4b430b49a7 Implement source sections compiler plugin
allows to compile only parts of the source files, denoted by top-level
"sections" (function with lambda param calls), but preserving original
file line/column numbers for easier diagnostics. Allow e.g. to compile
gradle "buildscript" section without preprocessing original file in
advance. See tests for examples.
2017-03-21 16:30:46 +01:00
Ilya Chernikov
63c276d444 Create extension points and register plugins earlier...
to allow plugins to affect source files creation
2017-03-21 16:30:45 +01:00
Alexander Udalov
7dfa3bea18 Update tools & libraries projects to use JDK 8 when needed 2017-03-21 17:45:53 +03:00
Alexander Udalov
33a0ae0fcd Skip kotlin-maven-plugin integration test if "skipTests" is defined
Similarly to kotlin-maven-plugin-test/pom.xml
2017-03-21 17:45:51 +03:00
Alexander Udalov
4273357adf Skip kotlin-maven-plugin-test tests if "skipTests" property is defined
"mvn -DskipTests ..." or "mvn -DskipTests=true ..." should not invoke
any tests
2017-03-21 17:45:51 +03:00
Sergey Igushkin
132393cc64 Fix for androidTest Gradle build
Replaced adding Kotlin sources with dependency on copy*KotlinClasses,
which might not be called since Android Gradle plugin sometimes
bypasses the tasks in finalizedBy .
Added a test for androidTest build apart from general build.

Issues: #KT-16897 Fixed
2017-03-21 17:30:59 +03:00
Dmitry Jemerov
ba9213234c Increase -Xmx for running Ant from AntTaskTestGenerated
The current value is no longer sufficient when running under JDK 8.
2017-03-21 15:19:55 +01:00
Sergey Igushkin
498c4dddea Fix for compatibility with Android Gradle plugin 2.4.0-alpha1
Deferred resolution of JAR-to-AAR mapping, since the Android Gradle
plugin now resolves dependencies at execution phase.
Dropped the code related to the Jack toolchain compatibility.
Throwing a build error when Jack is enabled.
Changed warning about Jack into a build error.
2017-03-21 16:56:09 +03:00
Simon Ogorodnik
439e158fb2 Fix failing test after migration to IDEA 171
BasicCompletionWeigherTestGenerated$ExpectedInfo.testPreferMatchingThis
Looks like IDEA now rearranges elements with same weight by length and
then alphabetically
2017-03-21 16:47:16 +03:00
Dmitry Jemerov
f0b7891d41 Turn off API usage inspection 2017-03-21 14:44:20 +01:00
Pavel V. Talanov
a03e9d340e Wrap sourceScope() and binaryScope() using sourceFilterScope
To avoid having to wrap at call site
2017-03-21 16:20:02 +03:00
Pavel V. Talanov
06fd1f3c44 Drop unused LibrarySourceHacks 2017-03-21 16:20:02 +03:00
Pavel V. Talanov
dec9fa0324 SourceNavigationHelper: fix navigation to callables
Previously we could differentiate between callables with the same name
    when relevant type declaration were in the same file only
Problem manifested most severely when several copies of sources were attached
    to the same library
2017-03-21 16:20:01 +03:00
Pavel V. Talanov
d9a9d50602 KotlinScriptConfigurationManager#notifyRootsChanges: run synchronously in tests
Allows to unmute some of the ScriptConfigurationNavigation tests
2017-03-21 16:20:00 +03:00
Pavel V. Talanov
88447d69cb Introduce ScriptDependenciesSourceModuleInfo
Implement SourceForBinaryModuleInfo api to support navigation
Support in getModuleInfo and KotlinCacheServiceImpl
2017-03-21 16:19:59 +03:00
Pavel V. Talanov
434018f679 ScriptConfigurationNavigationTest: test navigation to kotlin library 2017-03-21 16:19:59 +03:00
Pavel V. Talanov
115474b90f SourceNavigationHelper: use API to narrow search scope 2017-03-21 16:19:58 +03:00
Pavel V. Talanov
4dee108afe J2K SourceNavigationHelper: convert to Kotlin and prettify 2017-03-21 16:19:57 +03:00
Pavel V. Talanov
aa74ccf163 J2K SourceNavigationHelper: rename file 2017-03-21 16:19:57 +03:00
Pavel V. Talanov
4c94d931fa findDecompiledDeclaration: narrow decompiled declaration search scope
Search scope of library that descriptor originated from
Introduce API that matches binaries and its' sources via IdeaModuleInfos
2017-03-21 16:19:56 +03:00
Pavel V. Talanov
569e7ac593 getModuleInfo, minor: clarify parameter parameter 2017-03-21 16:19:55 +03:00
Pavel V. Talanov
c7f147d058 Introduce NavigationWithMultipleLibrariesTest
Test navigation to library decompiled and source declaration when
there are multiple copies of the same library in project
Related to ba1ee99e97
2017-03-21 16:19:54 +03:00
Pavel V. Talanov
47e77201d5 AbstractNavigateToLibraryTest: refactor, extract utility code 2017-03-21 16:19:54 +03:00
Alexander Udalov
2d1b15b6fb Drop usages of '-XX:MaxPermSize' in run configurations on JDK 8 2017-03-21 16:09:18 +03:00
Dmitry Jemerov
04b64fa30c Sort Kotlin versions loaded from Maven by number
Otherwise we get 1.0.7 on top of 1.1.1, which is suboptimal
2017-03-21 14:03:25 +01:00
Dmitry Jemerov
8f8db75bb4 getNonConfiguredModules(project, configurator) excludes modules already configured with other configurators
#KT-16381 Fixed
2017-03-21 14:02:05 +01:00
Dmitry Jemerov
95bc0813f8 Don't show "Configure Kotlin" notification with an empty list of configurators (context: KT-16070) 2017-03-21 14:02:05 +01:00
Dmitry Jemerov
9f8af1feea Refactor getNonConfiguredModules(Project)
Rename to getNonConfiguredModulesWithKotlinFiles() to match what it
actually does, remove duplicate configurator status check, extract code
for collecting all configurators
2017-03-21 14:02:05 +01:00
Dmitry Jemerov
b86fe60a24 Don't report "can be configured" status if the file is already configured with another Gradle configurator 2017-03-21 14:02:05 +01:00
Dmitry Jemerov
1f96ead801 "Configure Kotlin in project" handles modules from Gradle source roots
THose modules are now always collapsed to their base modules.
 #KT-11828 Fixed
2017-03-21 14:02:05 +01:00
Dmitry Jemerov
b1a65e4c74 Don't show pre-1.1.0 version of Kotlin in version chooser when configuring JS projects
#KT-16400 Fixed
2017-03-21 14:02:05 +01:00
Dmitry Jemerov
8e26d5257f Don't add stdlib-jre7 or stdlib-jre8 dependencies when configuring Kotlin with pre-1.1 version
#KT-16401 Fixed
2017-03-21 14:02:05 +01:00
Dmitry Jemerov
cd4636a1e5 Add current version to "Configure Kotlin in project" version chooser if it is a release version and it wasn't found in the search results
#KT-16571 Fixed
2017-03-21 14:01:37 +01:00
Dmitry Jemerov
0f21595e4b Don't show "Configure Kotlin" if module is configured, project is not
Report CAN_BE_CONFIGURED from Gradle configurator only if we didn't
find any file containing valid configuration (normally the top-level
project file in an Android project doesn't have any Kotlin
configuration, so we report CAN_BE_CONFIGURED even though the module
file contains valid configuration)
2017-03-21 14:01:37 +01:00
Dmitry Jemerov
b48b3b3237 Show "Configure Kotlin" notification at most once after project opening
Don't show notification after every sync; trigger it from
rootsChanged handler because the root model is not yet updated at
syncDone point
 #KT-16590 Fixed
2017-03-21 14:01:37 +01:00
Dmitry Jemerov
0a586291b6 Check jar name before trying to load JS library version
#KT-16596 Fixed
2017-03-21 14:01:37 +01:00
Dmitry Jemerov
09b60e3f77 JsLibraryStdDetectionUtil: J2K 2017-03-21 14:01:37 +01:00
Dmitry Jemerov
dffff77a5d JsLibraryStdDetectionUtil: rename to .kt 2017-03-21 14:01:37 +01:00
Dmitry Jemerov
ad3be8f8b5 Add test for checking JS runtime version 2017-03-21 14:01:37 +01:00
Dmitry Jemerov
1c0acee989 Remove obsolete code for removing obsolete JS library 2017-03-21 14:01:37 +01:00
shiraji
27e1462b00 Apply quick-fix "Make visible" for INVISIBLE_FAKE #KT-16131 Fixed 2017-03-21 13:50:49 +03:00
Alexander Udalov
d4500878cb Do not strip some classes from xercesImpl.jar in compiler.pro
Note that with this config, the kotlin-compiler.jar's size is increased
by 1.5Mb

 #KT-16968 Fixed
2017-03-21 13:03:19 +03:00
Alexander Udalov
af5fbef4ea Use JDK 1.6 to compile modules under "core"
Outputs of these modules go into kotlin-stdlib and kotlin-reflect, both
of which must be usable on Java 6
2017-03-21 13:03:18 +03:00
Dmitry Jemerov
d80891e823 Add xercesImpl.jar to core classpath as it's now required for JDOMUtil 2017-03-20 18:46:13 +01:00
Alexey Sedunov
2e3617adbb Spring Support: Fix tests in IDEA 2017.1
Filter out duplicate reference targets.
Fix test data as directory references are available
inside of string literals.
Fix test data as Spring @Autowired inspection
no more reports parameterless methods.
Fix gutter checking as configuration bean references now resolve
to @ComponentScan annotation
2017-03-20 18:46:12 +01:00
Simon Ogorodnik
2804264289 Fix regression of completion inside string templates
CompletionContributor should not store offsets inside
replacement zone(part of file which are replaced with
dummy identifier) in offsetMap
 #KT-16848 fixed
2017-03-20 18:46:11 +01:00
Dmitry Jemerov
cf18c2243f Fix test: check highlighting only in one direction
Otherwise, when we check the highlighting on one of the files, the text
of the other still contains the <lineMarker> annotation and can't be
indexed as valid Kotlin code.
2017-03-20 18:46:10 +01:00
Alexander Udalov
555b3f12ee Use LinkedHashSet instead of HashSet in DataFlowInfo.getCollectedTypes
This fixes DiagnosticsTestGenerated$Tests.testImplicitIntersection,
which began to fail after update to JDK 8 because the iteration order of
HashMap/HashSet has changed in JDK 8:
http://openjdk.java.net/jeps/180
http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/43bd5ee0205e
2017-03-20 18:46:09 +01:00
Mikhael Bogdanov
211b58ac6e kt1770.kt test rewrote during migration to 171 platform 2017-03-20 18:46:08 +01:00
Dmitry Jemerov
10aedaf0f4 Adjust test data for IDEA 2017.1
Since https://github.com/JetBrains/intellij-community/commit/9c8003c
deprecated methods are considered to be entry points, so the Safe
Delete quickfix is no longer available for them.
2017-03-20 18:46:08 +01:00
Alexander Udalov
999e1061b8 Update test data for ant task tests
Looks like javac 1.8 started to report compilation errors a bit
differently here
2017-03-20 18:46:07 +01:00
Alexander Udalov
449d1f6ad2 Fix KotlinVersionsTest, use SAX parser instead of DOM 2017-03-20 18:46:06 +01:00
Alexander Udalov
33e9e660c4 Fix JvmRuntimeDescriptorLoaderTestGenerated
- Use FULL_JDK instead of mock JDK in some tests because mock JDK is
  created from JDK 6 and full JDK is now JDK 8, so there are differences
  in the behavior in the compiler and at runtime
- Remove some '*.runtime.txt' files which were workarounds to JDK 6
  reflection issues regarding generic inner classes; code in these tests
  is now loaded exactly the same in the compiler and at runtime
- Change supertype in SupertypesAndBounds.kt: the class in the supertype
  is not relevant to that test, it checks that annotations can be loaded
  on types
2017-03-20 18:46:05 +01:00
Alexander Udalov
3c96099f7c Fix compileJavaAgainstKotlin tests
- Use another API to get file name out of a javac diagnostic
  (.getSource().getName()'s behavior changed in JDK 8)
- Delete .txt files for those tests which check that javac reported a
  compilation error; the order and content of declarations in those
  files is undefined
2017-03-20 18:46:05 +01:00
Nikolay Krasko
4edfd0d960 Move getting source position to manager thread in tests
Real usages are performed in this thread too. Using AWT now fails
under runInReadActionWithWriteActionPriorityWithRetries added in
b0e995b41e
2017-03-20 18:46:04 +01:00
Alexey Sedunov
ecd56c6a40 Safe Delete: Fix tests in IDEA 2017.1
Now Java refactoring checks for side effects when deleting
arguments, so instantiation of Kotlin FunctionN is treated as
"unsafe"
2017-03-20 18:46:03 +01:00
Alexey Sedunov
b65460c12f Move: Fix tests in IDEA 2017.1
Do not prevent usages search if target directory is not known yet.
Force content root configuration for multi-module tests
2017-03-20 18:46:02 +01:00
Mikhael Bogdanov
496a21254b Black box update 2017-03-20 18:46:01 +01:00
Alexey Tsvetkov
40574d31ac JPS tests: avoid using deprecated API 2017-03-20 18:46:00 +01:00
Dmitry Jemerov
3a8cf68541 Keep class file version during shrinking; generate Java 8 bytecode
sometimes
2017-03-20 18:45:59 +01:00
Dmitry Jemerov
4cae0538a8 Don't warn about ElementTraversal
IDEA now (since commit 6ff87c6) uses this class to build classpath
for Xerces, and we don't use Xerces
2017-03-20 18:45:59 +01:00
Dmitry Jemerov
0638106bf3 Fix NPE in tests when ProjectFileIndex is not available 2017-03-20 18:45:51 +01:00
Dmitry Jemerov
0d86bdd216 Remove Java 6/7 warning from expected output of the compiler 2017-03-20 18:45:51 +01:00
Dmitry Jemerov
2adacf74ac Reduce -Xmx of "All Non-Compiler Tests" configuration
This should prevent VM crashes on TeamCity
2017-03-20 18:45:50 +01:00
Dmitry Jemerov
a8bd529871 Register MetaLanguage.EP_NAME in J2K test 2017-03-20 18:45:49 +01:00
Dmitry Jemerov
61f157e89d Remove write action around finishLookup(), according to IJ 2017.1 req 2017-03-20 18:45:48 +01:00
Dmitry Jemerov
b9f326bfa1 Register MetaLanguage extension point in ParsingTestCase 2017-03-20 18:45:47 +01:00
Dmitry Jemerov
097ba45783 Fix service and EP registration according to changes in 2017.1
Remove ControlFlowFactory (which is now registered in the platform),
register MetaLanguage (new in 2017.1)
2017-03-20 18:45:46 +01:00
Dmitry Jemerov
a539939388 Fix testdata according to contract inference changes in 2017.1 2017-03-20 18:45:46 +01:00
Dmitry Jemerov
ad821e83bd Fix testdata according to comment selection changes in 2017.1 2017-03-20 18:45:45 +01:00
Dmitry Jemerov
d6709b726e Fix testdata according to changes in automatic renaming rules in 17.1 2017-03-20 18:45:44 +01:00
Dmitry Jemerov
374cf517e1 Don't try to create "add modifier" fix for read-only elements
This fixes a failure of KotlinCleanupInspectionTest on IDEA 17.1.
2017-03-20 18:45:43 +01:00
Dmitry Jemerov
3d98237304 Fix GradleFacetImportTest: run write action only in EDT 2017-03-20 18:45:43 +01:00
Dmitry Jemerov
49a4625368 Fix testdata: Android projects use kotlin-stdlib-jre7 2017-03-20 18:45:42 +01:00
Dmitry Jemerov
12fc89f35d Update to 171.SNAPSHOT to pick up fix for IDEA-169570; fix compilation 2017-03-20 18:45:41 +01:00
Nikolay Krasko
1d29c81346 ! (TODO) Update build test data in 171 2017-03-20 18:45:40 +01:00
Nikolay Krasko
7da424d53f Port setInPerformanceTest -> setInStressTest 2017-03-20 18:45:39 +01:00
Nikolay Krasko
e57b3651c2 Replace removed method in LibraryPresentationProviders 2017-03-20 18:45:39 +01:00
Nikolay Krasko
615f9d3a1f Try to avoid exception in getOffset() call 2017-03-20 18:45:38 +01:00
Nikolay Krasko
eb8415a1f3 Use new api from idea 171 in KotlinStepOverInlinedLinesHint 2017-03-20 18:45:37 +01:00
Nikolay Krasko
bcf29e6fbf Run tests in read action and not in EDT thread
Otherwise test will fail because of runInReadActionWithWriteActionPriority call in EDT
2017-03-20 18:45:36 +01:00
Nikolay Krasko
82a2a705fb Do not wrap analyze into write action priority in tests
In tests the code is executed in EDT and runInReadActionWithWriteActionPriority fails

See: MergingUpdateQueue.setPassThrough() and ExternalToolPassFactory() constructor
2017-03-20 18:45:36 +01:00
Nikolay Krasko
95061885b0 Update after separating JPS builders into two modules 2017-03-20 18:45:35 +01:00
Nikolay Krasko
3e6f57b684 Updated nullability in RunLineMarkerContributor 2017-03-20 18:45:34 +01:00
Nikolay Krasko
4f079d2768 LightQuickFixTestCase.parseActionHint() method was removed 2017-03-20 18:45:33 +01:00
Nikolay Krasko
d5aac7df25 Copy dropped method nameToCompare() to test utils 2017-03-20 18:45:33 +01:00
Nikolay Krasko
9f51b12193 Update guava 19.0 sources jar 2017-03-20 18:45:32 +01:00
Nikolay Krasko
ed9e083008 Remove unused import 2017-03-20 18:45:31 +01:00
Mikhail Glukhikh
e6cefba98b Fix imports vs 2016.3 (ResourceFoldingBuilder) 2017-03-20 18:45:30 +01:00
Mikhail Glukhikh
83a8b041ad Fix ConfigureProjectTestGenerated / GradleConfigureProject ... for branch 163 (jre7->jre8) 2017-03-20 18:45:29 +01:00
Nikolay Krasko
2eb6c393a4 Move android modules to Java 8 SDK 2017-03-20 18:45:29 +01:00
Dmitry Jemerov
715410a9bc Workaround for hanging test 2017-03-20 18:45:28 +01:00
Dmitry Jemerov
60a2151a33 Fix compilation
(cherry picked from commit 46b9041)
2017-03-20 18:45:27 +01:00
Yan Zhulanow
0995f2700e doMoveFile() now accepts not-null PsiDirectory
(cherry picked from commit 8a16c90)
2017-03-20 18:45:26 +01:00
Yan Zhulanow
59055e28ee CreateFileResourceQuickFix now accepts ResourceFolderType instead of ResourceType
(cherry picked from commit 55f350f)
2017-03-20 18:45:26 +01:00
Ilya Chernikov
4be5fcc14a Fix test code after UsefulTestCase api changes 2017-03-20 18:45:25 +01:00
Vyacheslav Gerasimov
180ae070ee Fixed KotlinAndroidResourceQuickFixProvider for AS 2.2 2017-03-20 18:45:24 +01:00
Dmitry Jemerov
594e2b6a77 fix compilation 2017-03-20 18:45:23 +01:00
Dmitry Jemerov
ab5067a0d3 remove write action around closeAndDeleteProject() 2017-03-20 18:45:23 +01:00
Dmitry Jemerov
b10073465c fix compilation of new lint checks against IDEA 163 2017-03-20 18:45:22 +01:00
Alexey Tsvetkov
05f278ce20 JPS: implement tracking of null annotations
#KT-12933 fixed
    #KT-14266 fixed
2017-03-20 18:45:21 +01:00
Alexey Tsvetkov
6d958eb32b Fix dist by ignoring some library classes during compiler shrinking 2017-03-20 18:45:20 +01:00
Dmitry Jemerov
b101550cae Advance idea.plugins.compatible.build 2017-03-20 18:45:19 +01:00
Dmitry Jemerov
e51018406f register PsiElementFinder extensions before JavaPsiFacade is registered 2017-03-20 18:45:18 +01:00
Dmitry Jemerov
036bfed984 Add resources_en.jar to properties plugin classpath 2017-03-20 18:45:18 +01:00
Konstantin Bulenkov
fcdd5e0a19 update Kotlin icons according to new IntelliJ style 2017-03-20 18:45:17 +01:00
Dmitry Jemerov
aced2e7eb4 Update compatible build number range 2017-03-20 18:45:16 +01:00
Dmitry Jemerov
a2b0b3d6eb fix compilation against branch 163 2017-03-20 18:45:15 +01:00
Yan Zhulanow
24c9b6e171 Migrate IDEA plugin code to Android Studio 2.2 (br 145) 2017-03-20 18:45:15 +01:00
Dmitry Jemerov
99af2a809b Update IDEA to 171.2613.7 2017-03-20 18:45:14 +01:00
Dmitry Jemerov
4d10b18fe1 Fix for 171 platform 2017-03-20 18:44:14 +01:00
Ilya Gorbunov
87c055cc61 Fix progression iterators to respect the Iterator contract.
#KT-16923 Fixed
2017-03-20 20:13:54 +03:00
Ilya Gorbunov
e5a28311bc Fix infinite sequence being terminated prematurely when being iterated without calling hasNext
#KT-16922 Fixed
2017-03-20 20:13:54 +03:00
Valentin Kipyatkov
f00ab135d6 Do not insert redundant space 2017-03-20 19:08:03 +03:00
Valentin Kipyatkov
3ec28f1242 Attempt to preserve partial substitution when detecting expected type for smart completion 2017-03-20 19:08:03 +03:00
Valentin Kipyatkov
b5dd2cc540 Completion of lambda parameters
Also changed policy for sorting of smart completion items in basic completion

 #KT-16800 Fixed
 #KT-12002 Fixed
2017-03-20 19:08:02 +03:00
Nikolay Krasko
c6b9aebfcf Minor: remove warning 2017-03-20 17:49:23 +03:00
Nikolay Krasko
afc0892d1f Synchronize state of parser and lexer for LONG_TEMPLATE_ENTRY (KT-14865)
Lexer monitors "long string template" state end and will produce
LONG_TEMPLATE_ENTRY_END token when it is reached. If parser continues
without waiting for it, it will eventually get handling token that
will produce irrelevant error. Such behaviour also breaks lazy
elements (LAMBDA_EXPRESSION in this case) contract: range of parsed text
in eager mode should be same to one parsed in lazy mode.

 #KT-14865 Fixed
2017-03-20 17:47:29 +03:00
Alexander Udalov
87ff70ee0f Replace JS metadata version with '$ABI_VERSION$' in tests
Similarly to the JVM metadata version, this is done in order to avoid
changing any test data when the version is increased
2017-03-20 17:22:29 +03:00
Alexander Udalov
e6f6b0dad5 JS: merge LibrarySourcesConfig into JsConfig 2017-03-20 17:22:29 +03:00
Alexander Udalov
bf90cb5cc0 JS: support -Xskip-metadata-version-check for incompatible ABI libraries
Allow the compiler to read such libraries without any errors, at the
risk of crashing with an exception.

Also fix a minor bug in the diagnostic message in LibrarySourcesConfig
and in the corresponding test in KotlinJpsBuildTest
2017-03-20 17:22:29 +03:00
Alexander Udalov
30dfd5cc1b JS: support '-Xskip-metadata-version-check' to allow pre-release libraries 2017-03-20 17:22:29 +03:00
Alexey Sedunov
a795a256f4 Configuration: Fix behavior of "output directory" control
Do not show file chooser twice.
Disable/enable control on component initialization and change of
"Use project settings" option

 #KT-16952 Fixed
 #KT-16953 Fixed
2017-03-20 17:19:13 +03:00
Simon Ogorodnik
f56af41d1e Fix TypeAliasConstructorDescriptor's to create only once when required
Some IDE features relates onto that same descriptors will remain same
between resolve calls
Fix it to be true for TypeAliasConstructorDescriptor's

 #KT-16265 fixed
2017-03-20 16:55:40 +03:00
Sergey Mashkov
23cbb83c75 IDL2K: drop garbage code, refactor to improve readability 2017-03-20 16:51:32 +03:00
Mikhail Zarechenskiy
1a4b9cb228 Show warning for mod from built-ins since API=1.1 2017-03-20 00:45:18 +03:00
Mikhail Zarechenskiy
e4188f889e Do not show warning for mod from built-ins when LV=1.0
#KT-16372 Fixed
2017-03-20 00:41:58 +03:00
Alexey Sedunov
071744a57f Extract Superclass/Interface: show inapplicability error before choosing the extraction container
#KT-15339 Fixed
2017-03-19 17:20:32 +03:00
Alexey Sedunov
eb9c775476 Navigation: Support NEW_AS_CONSTRUCTOR flag for constructor calls
#KT-15398 Fixed
 #KT-15536 Fixed
2017-03-19 17:20:24 +03:00
Alexey Sedunov
5e8cd654ec Find Usages: Fix processing of label references in 'return' expressions
#KT-7516 Fixed
2017-03-19 17:20:17 +03:00
Alexey Sedunov
275cdbbea7 Rename: Fix renaming of function by label reference inside of lambda argument
#KT-7520 Fixed
2017-03-19 17:20:10 +03:00
Alexey Sedunov
b1df91395a Minor: Use handler autodetection in some rename tests 2017-03-19 17:20:02 +03:00
Alexey Sedunov
871d42f05a Rename: Support renaming class by short reference to companion object
#KT-16108 Fixed
2017-03-19 17:19:55 +03:00
Alexey Sedunov
834cdd63ab Create from Usage: Support class generation by class literal expression
#KT-16188 Fixed
2017-03-19 17:19:48 +03:00
Alexey Sedunov
505a6bcbf2 JPS: Copy project-level settings before use
Sharing these settings for reading/writing
between different module during JPS build
may lead to compiler settings
(plugionOptions, in particular) of several
modules to be mixed

 #KT-16888 Fixed
2017-03-19 17:19:40 +03:00
Alexey Sedunov
2e1b4cd692 Misc: Fix test 2017-03-19 17:19:33 +03:00
Alexey Sedunov
2bb7bdfc3f Kotlin Facet: Fix reading of v1 configuration
Favor language/api version specified in <versionInfo> element
in case it differs from the one in
<option name="_commonCompilerArguments">

#KT-16861 Fixed
2017-03-19 17:19:26 +03:00
Alexey Sedunov
ca46100581 Kotlin Facet: Add tab for compiler plugin options
#KT-15768 Fixed
2017-03-19 17:19:18 +03:00
Alexey Sedunov
c264a2e15f Configuration: Improve presentation of the settings override warning 2017-03-17 21:08:44 +03:00
Alexey Sedunov
7c1249746f Kotlin Facet: Show scripting section only if target platform is JVM
#KT-16316 Fixed
2017-03-17 21:03:29 +03:00
Alexey Sedunov
f63828ff20 Configuration: Make UI improvements
Fix layout
Fix label names
Replace "Generate no warnings" checkbox with "Report compiler warnings"
2017-03-17 21:03:22 +03:00
Nikolay Krasko
f38753ee3c Remove explicit AppScheduledExecutorService shutdown (commit revert)
Revert "Problem: manually shutdown AppScheduledExecutorService to allow compiler stop properly"

The commit was added during update to 162.1024.1 to fix hangs in ant
tasks on teamcity because of some thread created in
AppScheduledExecutorService service.

Remove the commit because can't reproduce those hangs under 162.2946
(Probably 12a079ef41 fixed the hangs).

This should also be addressed in fix for https://youtrack.jetbrains.com/issue/IDEA-169562

This reverts commit 99a75021e1.
2017-03-17 18:02:11 +03:00
Nikolay Krasko
a63953432e Set "weak warning" severity for SameParameterValue inspection 2017-03-17 17:27:54 +03:00
Nikolay Krasko
52789df812 Minor: fix warnings in AbstractKotlinParsing.java 2017-03-17 17:27:53 +03:00
Sergey Mashkov
49c2f40f7d KT-16572 Add links to Mozilla Developer Network to kdocs of classes that we generate from IDL
regenerate
2017-03-17 13:04:34 +03:00
Sergey Mashkov
8842b6894e KT-16572 Add links to Mozilla Developer Network to kdocs of classes that we generate from IDL 2017-03-17 13:04:34 +03:00
Sergey Mashkov
02721a0b7f KT-16252 IDL2K: Add ItemArrayLike interface implementation to collection-like classes
regenerate
2017-03-17 13:04:33 +03:00
Sergey Mashkov
496795dd56 IDL2K eliminate attribute modality change caused by inheritance
always override attributes in class if it is inherited from an interface
2017-03-17 13:04:33 +03:00
Sergey Mashkov
a5d6541f1e KT-16252 IDL2K: Add ItemArrayLike interface implementation to collection-like classes 2017-03-17 13:04:32 +03:00
Vyacheslav Gerasimov
a795313c7d Add inspection for usages of Kotlin internal declarations in Java
#KT-11393 Fixed
2017-03-16 21:12:05 +03:00
Alexander Udalov
bd53922c64 Minor, don't shade com.sampullara in compiler-embeddable
See 73b879e
2017-03-16 15:40:06 +03:00
Alexander Udalov
332a0f5adc Use 'languageVersionSettings' extension instead of key directly
Also fix compilation of kotlin-script-util
2017-03-16 14:18:01 +03:00
Alexey Sedunov
0e4c3ec202 Kotlin Facet: Do not present imported -d/-cp in "Additional arguments" 2017-03-16 03:14:41 +03:00
Alexey Sedunov
88a394e892 Kotlin Facet: Validate "additional arguments"
Validate consistency of "additional arguments" with respect to settings specified in other UI controls
2017-03-16 03:14:40 +03:00
Alexey Sedunov
fa06965ed6 Kotlin Facet: Add import test for Maven project with submodule 2017-03-16 03:14:39 +03:00
Alexey Sedunov
cf9d7a0470 Kotlin Facet: Detect platform by stdlib dependency in android-gradle projects
#KT-16827 Fixed
2017-03-16 03:14:38 +03:00
Alexey Sedunov
040f5f88f2 Configuration: Show warning in project settings if they'are overridden in some modules(s) 2017-03-16 03:14:37 +03:00
Alexey Sedunov
5dc5ca551f Configuration: Make UI improvements
Use JTextField for output file prefix/postfix.
Use TextFieldWithBrowseButton for output directory
Improve layout
2017-03-16 03:14:36 +03:00
Alexey Sedunov
ee36abd73a Kotlin Facet: Drop obsolete facet detection infrastructure 2017-03-16 03:14:35 +03:00
Alexey Sedunov
5c55b9fbbe Configuration: Check that project-level common arguments are not changed through platform-specific holders 2017-03-16 03:14:34 +03:00
Alexey Sedunov
ce434585e3 J2K: Convert BaseKotlinCompilerSettings and its inheritors 2017-03-16 03:14:32 +03:00
Alexey Sedunov
f8e5065845 J2K: Convert BaseKotlinCompilerSettings and its inheritors (rename to .kt) 2017-03-16 03:14:31 +03:00
Pavel V. Talanov
f1c0d5316f Refactor delegate members to light members conversion 2017-03-15 20:55:42 +03:00
Pavel V. Talanov
eedcc19209 J2K KtLightClassBase: rename file 2017-03-15 20:55:41 +03:00
Pavel V. Talanov
04591bb938 LightClassDataHolder: refactor, extract subinterfaces 2017-03-15 20:55:40 +03:00
Pavel V. Talanov
6d595e30c2 ClassFileFactory, minor: make done() public and use in LightClassDataProvider 2017-03-15 20:55:40 +03:00
Pavel V. Talanov
d62db8dc6b LightClassGenerationSupport: refactor, minor
Use typealias where appropriate
Less verbose method names
2017-03-15 20:55:39 +03:00
Pavel V. Talanov
a645dc109a KotlinLightClassBuilderFactory, LightClassBuilder: refactor, clarify 2017-03-15 20:55:38 +03:00
Pavel V. Talanov
c73e58516b Refactor LightClassDataProvider: drop LightClassDataProvider class
Move code to inheritors
Improve api to avoid getting empty file lists in random places
2017-03-15 20:55:37 +03:00
Pavel V. Talanov
ab0d939626 searchHelpers: remove hack relying on light classes triggering resolve 2017-03-15 20:55:08 +03:00
Pavel V. Talanov
feae5079ed Light classes: refactor, introduce lazyPub util to reduce verbosity 2017-03-15 20:55:07 +03:00
Pavel V. Talanov
ba185d7616 LightClassDataProvider: refactor, extract class filters to separate classes 2017-03-15 20:55:05 +03:00
Pavel V. Talanov
48cae0e480 KtLightField/Method: Use equality in equivalence checks
Avoid computing delegate to determine equivalence
2017-03-15 20:55:03 +03:00
Pavel V. Talanov
8054020f61 IDELightClassContexts: @PublishedApi affects codegen 2017-03-15 20:55:02 +03:00
Pavel V. Talanov
d846d05527 PsiElementChecker: minor
Check own members before inners' since it triggers the computation of outer stub
2017-03-15 20:55:01 +03:00
Pavel V. Talanov
d34b73befb Light class codegen: all objects are considered static
Simplify code handling access flag computation
Fix a problem where kotlin nested object wasn't producing a nested light class
2017-03-15 20:55:01 +03:00
Pavel V. Talanov
d94da5af40 Frontend: create component functions for properties with error types
Fixes an inconsistency in light classes where we could have different
  class structure depending on whether the type was resolved
2017-03-15 20:55:00 +03:00
Pavel V. Talanov
fa58f1b4d7 KtLightMethod(Field): use dummyDelegate to determine modifier properties 2017-03-15 20:54:59 +03:00
Pavel V. Talanov
abf206a134 KtLightMethod(Field): do not use clsDelegate in hashCode && equality checks 2017-03-15 20:54:58 +03:00
Pavel V. Talanov
fee29c47c8 KtLightMethod: use dummy delegate to compute parameter count and isContructor 2017-03-15 20:54:56 +03:00
Pavel V. Talanov
3e7357a5d7 IDELightClassTest: provide tools to check laziness of light class construction
StubComputationTracker knows which context was used to construct light class
2017-03-15 20:54:55 +03:00
Pavel V. Talanov
daef8a0eed Light classes in IDE: Make light class delegate construction a two step process
Step 0: Light class object is created, no delegates are computed
Step 1: constructs dummy delegate which can not be relied upon to know signature of any member
		It can be used to construct light field and light method objects
		(which can correctly respond to some queries) before constructing real delegate
Step 2:
		Construct real delegate if dummy delegate is not enough to respond to a query

This speeds up multiple scenarios where getMethods() and getFields() are called on numerous classes

Dummy delegate's faster consruction is achieved by using specially setup dumb analysis instead of ide analysis

Introduce LazyLightClassDataHolder: which manages creation of Step 1 and Step 2 delegates
Introduce MemberIndex: keeping track of member creation order, helps matching light class delegates created in different contexts
KtLightMethod and Field: make use of dummy delegate
KtLightMethod no longer extends LightMethod since it requires eager delegate construction
KtLightMethod now implements PsiAnnotationMethod for convenience (ClsMethodImpl implements PsiAnnotationMethod)
2017-03-15 20:54:55 +03:00
Pavel V. Talanov
ed9e94c632 KtLightModifierListWithExplicitModifiers: fix equals 2017-03-15 20:53:59 +03:00
Pavel V. Talanov
d01aaeb65c Refactor light classes: Delegate LightClassDataHolder construction to LightClassGenerationSupport 2017-03-15 20:53:58 +03:00
Pavel V. Talanov
00e84fb483 Light classes: Refactor construction
Introduce LightClassDataHolder: which now is reponsible for constructing clsDelegate
Move out light big chunk of delegate building logic out of LightClassDataProvider into LightClassBuilder
LightClassData only holds information about single class
2017-03-15 20:53:37 +03:00
Pavel V. Talanov
22fb9ec5e1 Refactor light classes: move light members creation to their respective classes 2017-03-15 20:52:51 +03:00
Pavel V. Talanov
15b063d236 J2K LightClassGenerationSupport: rename file 2017-03-15 20:52:50 +03:00
Pavel V. Talanov
dd2d9c1dc2 J2K LightClassGenerationSupport: convert code 2017-03-15 20:52:49 +03:00
Pavel V. Talanov
71161e218b Refactor LightClassData: remove redundant entities 2017-03-15 20:52:48 +03:00
Pavel V. Talanov
0a0e628068 Refactor: move code to new package 2017-03-15 20:52:26 +03:00
Pavel V. Talanov
ac368ac182 Light classes test: test methods & fields with same name 2017-03-15 20:52:25 +03:00
Pavel V. Talanov
955fe9e1e6 Light class tests: add tests
- test Jvm* annotations with wrong arguments
  - test JvmStatic annotation
  - test JvmName annotation
2017-03-15 20:52:24 +03:00
Pavel V. Talanov
dbcd141a46 Extract superclass from AnnotationResolver 2017-03-15 20:52:24 +03:00
Pavel V. Talanov
8794005234 JvmPlatform#getDefaultImports: avoid recomputing JvmBuiltins
We need to use LockBasedStorageManager() (instead of NO_LOCKS) since getDefaultImports()
    can be called concurrently in certain scenarios
2017-03-15 20:52:23 +03:00
Pavel V. Talanov
bbe3b3cabe WrappedType: introduce WrappedTypeFactory to encapsulate wrapped types creation 2017-03-15 20:52:22 +03:00
Pavel V. Talanov
85420d1ffd MemberCodegen: Do not try to write inner class metadata for inner class 2017-03-15 20:51:22 +03:00
Pavel V. Talanov
1441aea2ea Light classes: allow light classes for inner/nested classes to be build separately
Avoid analyzing/generating bytecode for outers
2017-03-15 20:51:22 +03:00
Pavel V. Talanov
6924ddeace Clarify logic in KotlinTypeMapper.mapType() dealing with enum entries
This allows to write correct class signatures for enum entries
    regardless of whether ASM_TYPE slice was written to
2017-03-15 20:51:20 +03:00
Pavel V. Talanov
6f6a595fef Refactor FileScopeFactory 2017-03-15 20:51:19 +03:00
Pavel V. Talanov
d7c1993194 FileScopeFactory: postpone default import resolver construction 2017-03-15 20:51:18 +03:00
Pavel V. Talanov
babb3b557d J2K ImportPath: kotlinify 2017-03-15 20:51:17 +03:00
Pavel V. Talanov
50d0f5bde6 J2K ImportPath: autoconvert 2017-03-15 20:50:12 +03:00
Pavel V. Talanov
91e8d9e211 J2K ImportPath: rename file 2017-03-15 20:49:22 +03:00
Simon Ogorodnik
e7753c31db Minor: Add Dokka format param to build-docs script
To have an ability to change it in TeamCity between custom builds
2017-03-15 19:43:14 +03:00
Simon Ogorodnik
38047240d3 Fix documentation for stdlib
Add forgotten files to file list used by
Dokka when generating documentation
2017-03-15 18:26:52 +03:00
Simon Ogorodnik
5c4ba53f42 Optimization of Basic Code Completion
Now we first search for simple reference variants, then for extensions
 Because extension search is slow
 #KT-16856
2017-03-15 17:50:29 +03:00
Simon Ogorodnik
4906ddfc29 Optimization of Basic Code Completion
Now we don't perform code formatting on temporary psi used
  in ShadowedDeclarationFilter
  #KT-16856
2017-03-15 17:50:20 +03:00
Mikhail Glukhikh
bbab0f11ca Cleanup: fix some "leaking this" warnings 2017-03-15 17:36:08 +03:00
Mikhail Glukhikh
045a23ae10 Cleanup: apply "Convert lambda to reference" 2017-03-15 17:36:02 +03:00
Mikhail Glukhikh
b121bf8802 Cleanup: fix some compiler warnings (mostly deprecations, javaClass) 2017-03-15 17:35:31 +03:00
Mikhail Glukhikh
d0cc1635db Cleanup: apply "Use synthetic property access syntax" 2017-03-15 16:13:40 +03:00
Mikhail Glukhikh
1375267996 Cleanup: apply redundant curly braces in string template inspection 2017-03-15 16:13:22 +03:00
Mikhail Glukhikh
e37800d056 Cleanup: apply redundant string template inspection 2017-03-15 16:12:59 +03:00
Igor Chevdar
10ea2883f7 Supported KProperty2 and KMutableProperty2 for delegated properties
Consider this code:
object Delegate {
    operator fun getValue(t: Any?, p: KProperty<*>): String {
        return ""
    }
}

class A {
    val String.ext by Delegate
}

then the type of <p> is KProperty2 (it has 2 receivers).

Test fix + review fixes
2017-03-15 12:20:57 +03:00
Alexander Udalov
d58d75c6ef Refactor "do not check impl" flag for multi-platform projects
Instead of LanguageFeature, make it an AnalysisFlag, which is more clear
2017-03-15 11:03:05 +03:00
Alexander Udalov
56201a6dc4 Refactor skipMetadataVersionCheck flag
To make addition of other flags easier in the future, provide a more
abstract 'isFlagEnabled' in LanguageVersionSettings
2017-03-15 11:03:04 +03:00
Alexander Udalov
7a240b63c7 Use LanguageFeature.State enum instead of CoroutineSupport 2017-03-15 11:03:03 +03:00
Alexander Udalov
34e131c928 Refactor LanguageVersionSettings.isApiVersionExplicit
Pass it in the CompilerConfiguration instead of LanguageVersionSettings.
This is better because LanguageVersionSettings is accessible everywhere
in front-end and back-end, and this flag should not be used there
2017-03-15 11:03:01 +03:00
Alexander Udalov
32826c1686 Introduce LanguageFeature.State, drop coroutines-related pseudofeatures
Previously there were three LanguageFeature instances -- Coroutines,
DoNotWarnOnCoroutines and ErrorOnCoroutines -- which were handled very
awkwardly in the compiler and in the IDE to basically support a language
feature with a more complex state: not just enabled/disabled, but also
enabled with warning and enabled with error. Introduce a new enum
LanguageFeature.State for this and allow LanguageVersionSettings to get
the state of any language feature with 'getFeatureSupport'.

One noticeable drawback of this approach is that looking at the API, one
may assume that any language feature can be in one of the four states
(enabled, warning, error, disabled). This is not true however; there's
only one language feature at the moment (coroutines) for which these
intermediate states (warning, error) are handled in any way. This may be
refactored further by abstracting the logic that checks the language
feature availability so that it would work exactly the same for any
feature.

Another issue is that the difference among ENABLED_WITH_ERROR and
DISABLED is not clear. They are left as separate states because at the
moment, different diagnostics are reported in these two cases and
quick-fixes in IDE rely on that
2017-03-15 11:03:00 +03:00
Alexander Udalov
cf7048dd0f Do not inject CompilerConfiguration into compiler front-end
Inject LanguageVersionSettings instead; all information relevant to the
analysis should be now passed via an instance of LanguageVersionSettings
(which should be renamed to a more general name in the future).

This is partially a revert of d499998 and related commits
2017-03-15 11:02:59 +03:00
Alexander Udalov
a879cb0cfd Minor, take LanguageVersionSettings in CompilerDeserializationConfiguration 2017-03-15 11:02:58 +03:00
Alexander Udalov
ac530ac49c Move skipMetadataVersionCheck flag to LanguageVersionSettings
This makes it possible to avoid the CompilerConfiguration instance in
injectors, because CompilerDeserializationConfiguration was the only
left component that required it.

LanguageVersionSettings is not a good name for this entity anymore, it
should be renamed in the future
2017-03-15 11:02:58 +03:00
Alexander Udalov
f5d4dd33da Inject JvmTarget into some JVM-specific call checkers
This makes it possible to drop CompilerConfiguration from
CallCheckerContext, which in turn helps to avoid passing the entire
CompilerConfiguration instance through front-end
2017-03-15 11:02:57 +03:00
Alexander Udalov
573c6ab5d4 Move JvmTarget to frontend.java, introduce TargetPlatformVersion
Previously JvmTarget was declared in module 'util' which is accessible
for example from 'frontend', which is not very good.

Also add a superinterface named TargetPlatformVersion which is going to
be used in platform-independent injectors in 'frontend' in the following
commits. Use it in one place (LanguageVersionSettingsProviderImpl.kt)
instead of DescriptionAware because TargetPlatformVersion sounds like a
better abstraction than DescriptionAware here
2017-03-15 11:02:56 +03:00
Denis Zharkov
d2cd5d46fa Minor. Use static method from super class
It was a code with warning
2017-03-15 10:47:12 +03:00
Denis Zharkov
dcc98e3839 Improve check for statements-only postfix templates
Before this change the check was quite complicated
because of cases like:
for (i in 1..9)
    foo(i)<caret>

It's not located in a block, but in the same time it's a stament.
So we had a tricky heuristics that if is parent is not a block, then
we should check if element isn't used as expression.

Of course this heuristics is wrong, e.g. for import/package nodes.

The solution is to reuse similar logic from BasicExpressionTypingVisitor.
it has been checked once that statement container is one of:
- KtBlockExpression
- KtContainerNodeForControlStructureBody
- KtWhenEntry

So there's no need to check anything else

 #KT-14986 Fixed
 #KT-14483 Fixed
2017-03-15 10:47:12 +03:00
Denis Zharkov
78ffe47bf8 Fix samples for 'iter' postfix template
#KT-14727 Fixed
2017-03-15 10:47:12 +03:00
Denis Zharkov
bd88919411 Refine predicate for 'iter' postfix template
Use IterableTypesDetection to determine if the given expression may be iterated

 #KT-14134 Fixed
 #KT-14129 Fixed
2017-03-15 10:47:12 +03:00
Denis Zharkov
465a424af4 Refactor postfix template selector
Allow to specify predicate by KtExpression instead of type predicate
It will be used for `for` template which need a context to determine
whether the expression is iterable
2017-03-15 10:47:12 +03:00
Vyacheslav Gerasimov
b8ebc087e2 Add inspection for calls of function with lambda expression body
Added "Unused return value of a function with lambda expression body" inspection with quickfix "Remove '=' token from function declaration"

#KT-10393 Fixed
2017-03-15 00:22:31 +03:00
Vyacheslav Gerasimov
087551ad61 Implement quick fix for "Invalid type of annotation member"
Quickfix changes array of boxed type to array of primitive type

#KT-8568 Fixed
2017-03-15 00:21:24 +03:00
Vyacheslav Gerasimov
b8563f7fcf Fix KotlinUastTypesTest.testCycleInTypeParameters 2017-03-15 00:20:40 +03:00
Mikhail Glukhikh
cab80812ef KT-13111: lambda --> reference supports also object members 2017-03-14 18:45:08 +03:00
Mikhail Glukhikh
631f58f27f Lambda --> reference: correct handling of companion references
Reference receivers are named more accurately now #KT-13341 Fixed
2017-03-14 18:45:06 +03:00
Mikhail Glukhikh
2c692de98f KT-13111: lambda --> reference support methods called via this now 2017-03-14 18:45:05 +03:00
Mikhail Glukhikh
19db4869e6 Lambda --> reference: correct handling of parameter-less function
Issue #KT-15556 Fixed
2017-03-14 18:45:04 +03:00
Mikhail Glukhikh
b6974a88c5 Refactoring: convert lambda --> reference intention 2017-03-14 18:45:02 +03:00
Mikhail Glukhikh
3a14a5c461 Lambda --> reference supports bound references now #KT-13111 Fixed 2017-03-14 18:45:01 +03:00
Mikhail Glukhikh
831467891c Reference --> lambda supports bound references now #KT-16292 Fixed 2017-03-14 18:45:00 +03:00
Yan Zhulanow
f6734e74e1 Minor, SamWithReceiver: Fix services for kotlinc CLI execution
Move service files to META-INF to support execution from CLI (using PluginCliParser).
2017-03-14 18:36:40 +03:00
Mikhael Bogdanov
23698f93e0 Fix reification for crossinline lambdas inlined into object literal
Inline lambda could capture reified parameter of containing inline function ('a' function)
when it is inlined in another one.
If it's inlined in any anonymous object we should track it and
add reification marker to such anonymous object instance creation
to rewrite it on inlining bytecode of 'a' function.

  #KT-15997 Fixed
2017-03-14 15:54:13 +01:00
Alexey Sedunov
6b6d7a5030 Configuration: Don't create kotlinc.xml if the settings don't differ from the defaults
#KT-16647 Fixed
2017-03-14 15:33:11 +03:00
Alexey Sedunov
e8749e639c Kotlin Facet: Add link to project-level compiler settings UI
#KT-16022 Fixed
2017-03-14 15:33:10 +03:00
Alexey Sedunov
8c91dc579a Kotlin Facet: Show project-level settings when "Use project settings" is selected
#KT-16023 Fixed
2017-03-14 15:33:09 +03:00
Alexey Sedunov
9bbea47f93 Kotlin Facet: Parse and merge compiler arguments specified in <arg> elements instead of appending them (to avoid duplication)
#KT-16776 Fixed
2017-03-14 15:33:08 +03:00
Alexey Sedunov
e5a128ab2e JPS: Parse and merge additional arguments with primary ones instead of
appending them (to avoid duplication)
 #KT-16788 Fixed
2017-03-14 15:33:07 +03:00
Alexey Sedunov
73b879ea89 Misc: Include cli-parser 1.1.2 sources into the project under different package and drop original library dependency
This would allow building the project with Kotlin JPS plugin on TeamCity where older library takes precendence due to appearing earlier in JPS classpath
2017-03-14 15:33:06 +03:00
Dmitry Jemerov
e037e9de39 Do not cache contents in VFS when reading contents of .jar files
This follows the standard IDEA policy of caching file contents.
2017-03-14 13:06:47 +01:00
Dmitry Jemerov
8d1d76cdae Try to recover from corrupt VFS data for a .kotlin_module file
#KT-13135 Fixed
2017-03-14 13:06:29 +01:00
Mikhail Zarechenskiy
da53317357 Fix exception when type parameters appear in object declaration
#KT-14536 Fixed
2017-03-14 01:10:00 +03:00
Mikhail Zarechenskiy
0568bc3ef1 Add note about JS to the changelog 2017-03-13 21:09:17 +03:00
Mikhail Zarechenskiy
fd80c0d1d1 Remove KT-15200 from the changelog
It was postponed until 1.1.2
2017-03-13 20:38:43 +03:00
Mikhail Zarechenskiy
05ef705609 Add IGNORE_BACKEND directive for native automatically
Also parse correctly case IGNORE_BACKEND: JS, NATIVE
2017-03-13 19:56:13 +03:00
Dmitry Jemerov
006062499c Optimize imports (to fix compilation under 171 branch) 2017-03-13 16:34:48 +01:00
Mikhail Zarechenskiy
774aa720b4 Update Changelog for version 1.1.1 2017-03-13 16:45:25 +03:00
Dmitry Petrov
a0a8beee82 Handle TypeAliasDescriptor in AdaptiveClassifierNamePolicy
(as ClassDescriptor)
2017-03-13 14:15:27 +03:00
Mikhael Bogdanov
ce3b455f57 Fix for KT-16801: Accessors of @PublishedApi property gets mangled
#KT-16801 Fixed
2017-03-13 10:51:10 +01:00
Dmitry Petrov
c46164481a KT-15871 Unnecessary boxing for equality operator on inlined primitive values
Allow kotlin.jvm.internal.Intrinsics#areEqual for boxed values.
Rewrite to primitive equality.

NB we can't do that for Float and Double, because java.lang.Float#equals
and java.lang.Double#equals behave differently from primitive equality comparisons.
2017-03-13 09:04:31 +03:00
Dmitry Petrov
a087ea559f Eliminate redundant CHECKCAST instructions
CHECKCAST is redundant if the corresponding static type exactly matches the target type.
CHECKCAST instructions to-be-reified should not be eliminated.

KT-14811 Unnecessary checkcast generated in parameterized functions
KT-14963 unnecessary checkcast java/lang/Object
2017-03-13 09:04:31 +03:00
Dmitry Petrov
ec403bfdbc KT-16245 Redundant null-check generated for a cast of already non-nullable value
KT-16194 Code with unnecessary safe call contains redundant boxing/unboxing for primitive values
KT-12839 Two null checks are generated when manually null checking platform type

Recognize some additional cases of trivial null checks and trivial instance-of checks.

A variable is "checked for null", if it is:
- a function parameter checked with 'INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull'
- checked for nullability with 'IFNULL/IFNONNULL'
- checked for nullability with 'INSTANCEOF'
  (if objectref is instance-of T, then objectref is non-null)

Before analyzing nullability, introduce synthetic assumptions for execution branches
where a variable is guaranteed to be null or not null. For example, the following bytecode:

     ALOAD 1 // Ljava/lang/String;
     IFNULL L
     <non-null branch>
  L:
     <null branch>

is transformed to

     ALOAD 1
     IFNULL L1
     NEW java/lang/String
     ASTORE 1            // tells analyzer that variable 1 is non-null
     <non-null branch>
  L:
     <null branch>
  L1:
     ACONST_NULL
     ASTORE 1            // tells analyzer that variable 1 is null
     GOTO L

After the analysis is performed on a preprocessed method,
remember the results for "interesting" instructions
and revert the preprocessing transformations.

After that, perform bytecode transformations as usual.

Do not transform INSTANCEOF to-be-reified, because reification at call site
can introduce null checks. E.g.,

    inline fun <reified T> isNullable() = null is T
    ...
    assert(isNullable<String?>())
2017-03-13 09:04:31 +03:00
Dmitry Petrov
3c09a26e16 KT-5248 Don't wrap variable if it is captured only in inlined closures
Remove non-escaping Ref's on bytecode postprocessing pass.
2017-03-13 09:04:31 +03:00
Dmitry Petrov
3fc106572e Make redundant null check optimization independent of boxing optimization algorithm.
Run DCE after each single redundant null check optimization pass.
2017-03-13 09:04:31 +03:00
Ilya Matveev
eda43c8b45 Mute tests with standard collection extensions in native 2017-03-10 19:59:37 +03:00
Ilya Matveev
29e5ad5abe Mute tests with '::class' in native backend 2017-03-10 19:59:37 +03:00
Ilya Matveev
8a3fa2e4e5 Fix expected SMAPs after test muting for native 2017-03-10 19:59:37 +03:00
Ilya Matveev
a5e4e0284e Mute some box tests for native backend
This patch mutes the following test categories:
   * Tests with java dependencies (System class,
     java stdlib, jvm-oriented annotations etc).
   * Coroutines tests.
   * Reflection tests.
   * Tests with an inheritance from the standard
     collections.
2017-03-10 19:59:37 +03:00
Alexander Udalov
d21d362f0f Allow enum entries in double colon LHS with LV = 1.0
#KT-16782 Fixed
2017-03-10 19:44:00 +03:00
Denis Zharkov
39055229a1 Add diagnostic info to assertion on type argument consistency 2017-03-10 18:17:50 +03:00
Vyacheslav Gerasimov
830bf62d94 Fix SOE from UAST in containsLocalType
containsLocalType now properly handles start projections
#KT-16680 Fixed
2017-03-10 17:30:21 +03:00
Simon Ogorodnik
4e98394c38 Fix Sample reference to resolve cross-module packages correctly
Now @sample links to FqName in IDE will be resolved correctly
 Cause now we resolve packages over all modules in project
 #KT-14710 fixed
2017-03-10 15:33:47 +03:00
Nikolay Krasko
688802de51 Check breakpoints work in delegate initializer
Additional test after review
2017-03-10 14:59:37 +03:00
Nikolay Krasko
e6ee933b27 Fix "smart step into" for classes with complex hierarchy (KT-16667)
#KT-16667 Fixed
2017-03-10 14:58:21 +03:00
Nikolay Krasko
6d9b519bb2 Use new utility method for getting lexical scope
It's expected that for call expressing some nearest parent will have
lexical scope written in binding context. Under this circumstances it's
refactoring.
2017-03-10 14:58:17 +03:00
Nikolay Krasko
0a7a73d4be Refactoring: extract method for getting lexical scope without facade 2017-03-10 14:58:16 +03:00
Nikolay Krasko
9120ccc054 Fix breakpoints in inline calls in fields initialization (KT-16525)
Backend generates properties initializer in constructor context

 #KT-16525 Fixed
2017-03-10 14:58:15 +03:00
Nikolay Krasko
d886cd7d06 Fix breakpoints when inline call is in qualified expression (KT-16062)
Scope is stored for DOT_QUALIFIED_EXPRESSION not directly for
CALL_EXPRESSION.

 #KT-16062 Fixed
2017-03-10 14:58:14 +03:00
Nikolay Krasko
2719016539 Fix search of correspondent call expression by element (KT-11234)
getStrictParentOfType() looks for nearest parent of given type

In complex expressions like:

SamConversion.doAction({
  inlineCall {
    {
      // here <--
    }()
  }
})

doAction was found twice, while inlineCall was skipped.

See code:
// call(param, { <it> })
lambdaExpression?.typedParent<KtValueArgument>()?.typedParent<KtValueArgumentList>()?.typedParent<KtCallExpression>() ?:

// call { <it> }
lambdaExpression?.typedParent<KtLambdaArgument>()?.typedParent<KtCallExpression>()

 #KT-11234 Fixed
2017-03-10 14:58:13 +03:00
Nikolay Krasko
b240ae791c Minor: extract variable 2017-03-10 14:58:12 +03:00
Denis Zharkov
52d11eb22b Minor. Revert workarounds for problem on KClass from annotation
See KT-9453 for clarification
2017-03-10 13:49:07 +03:00
Denis Zharkov
82d7a269ed Minor. Make sure that implicit contract of mapSignature is satisfied
For ordinary functions mapSignature doesn't use original descriptor
and maps the given descriptor itself, but for constructor it obtained
the original value parameters.

Necessary `getOriginal` calls were added to the call-sites
2017-03-10 13:49:06 +03:00
Denis Zharkov
394c68c326 Minor. Move unwrapping of FunctionImportedFromObject
It should not affect the semantics, because mapSignatureWithCustomParameters
can only be called with FunctionImportedFromObject from mapSignature.

At the same time it's very nice to have all of these kinds
of custom unwrapping in the same place
2017-03-10 13:49:06 +03:00
Denis Zharkov
530214fcee Minor. Simplify mapping to callable method
There's no need in unwrapping for TypeAliasConstructorDescriptor
because mapSignatureSkipGeneric/mapDefaultMethod already do it
in some moment, and ConstructorDescriptor has getConstructedClass method
for mapping its owner
2017-03-10 13:49:05 +03:00
Denis Zharkov
be90f7d331 Make type aliases constructors return correct original descriptors
The problem was that when resolving super-calls we used known substitutor
when creating a type alias constructor, thus its original return itself,
while it's expected that it should return the descriptor before substitution

The main idea of the fix that `createIfAvailable` should always return
unsubstituted constructor.

Note that known substitutor for type alias constructor should be based
on abbreviation.

The test change seems to be correct as PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
is already reported.
Beside this, resolution behavior isn't expected to be changed dramatically
2017-03-10 13:49:05 +03:00
Denis Zharkov
2b21280ba9 Unwrap underlying typealias constructor earlier
The problem is very subtle (see the test): when generating a signature
for an object literal we also were mapping its super-class
(a type alias here).

Although we did unwrap its underlying constructor to map it properly
we did too late (after obtaining value parameters from the type alias constructor descriptor).

Another problem is that TypeAliasConstructorDescriptor.getOriginal
in the case does return itself, while it's expected to return
unsubstituted version

Note: everything works for common calls for such constructors
because they mapped through mapCallableMethod which contains
another custom unwrapping of type alias constructors

 #KT-16555 Fixed
2017-03-10 13:45:37 +03:00
Denis Zharkov
8761ef6694 Minor. Rename mapSignature overload to mapSignatureWithCustomParameters 2017-03-10 13:45:37 +03:00
Denis Zharkov
7173e56393 Make computation of arguments for raw types lazy
See how we translate raw types to Kotlin model:
RawType(A) = A<ErasedUpperBound(T1), ...>
ErasedUpperBound(T : G<t>) = G<*> // UpperBound(T) is a type G<t> with arguments
ErasedUpperBound(T : A) = A // UpperBound(T) is a type A without arguments
ErasedUpperBound(T : F) = UpperBound(F) // UB(T) is another type parameter F

Stack overflow happens with the following classes:
class A<X extends B> // NB: raw type B in upper bound
class B<Y extends A> // NB: raw type A in upper bound

when calculating raw type for A, we start calculate ErasedUpperBound(Y),
thus starting calculating raw type for B => ErasedUpperBound(X) => RawType(A),
so we have SOE here.
The problem is that we calculating the arguments for these raw types eagerly,
while from the definition of ErasedUpperBound(Y) we only need a type constructor
of raw type B (and the number of parameters), we don't use its arguments.

The solution is to make arguments calculating for raw types lazy

 #KT-16528 Fixed
2017-03-10 13:30:33 +03:00
Mikhael Bogdanov
f2fea9a04a Generate unboxing operation on boxed class not Number.class when possible 2017-03-10 10:04:30 +01:00
Mikhael Bogdanov
5e80d80797 Fix for KT-16732: Type 'java/lang/Number' (current frame, stack[0]) is not assignable to 'java/lang/Character
#KT-16732 Fixed
2017-03-10 10:04:29 +01:00
Mikhail Glukhikh
32bdb6becb KT-16714 related refactoring of tryRunWriteAction (now runWriteAction is not used if intention is called from J2K) 2017-03-10 10:46:49 +03:00
Alexey Sedunov
faa0dff649 Kotlin Facet: Do no present compiler plugin classpaths and options in additional arguments string
#KT-16313 Fixed
2017-03-09 23:06:52 +03:00
Alexey Sedunov
cc20c66bfc Kotlin Facet: Fix platform detection by Maven execution goals
#KT-15947 Fixed
 #KT-16342 Fixed
2017-03-09 23:06:47 +03:00
Alexey Sedunov
e8640b441d JPS: Fix earlier configurations with incorrect combination of language and API version 2017-03-09 23:06:42 +03:00
Alexey Sedunov
811b8978c2 Kotlin Facet: Escape additional compiler arguments when converting them to string and unescape before parsing
#KT-16700 Fixed
2017-03-09 23:06:38 +03:00
Alexey Sedunov
c5ee28da05 Kotlin Facet: Detect module platform by gradle plugin
#KT-16703 Fixed
 #KT-16342 Fixed
2017-03-09 23:06:33 +03:00
Alexey Sedunov
26537cd8fc Kotlin Facet: Distinguish compiler arguments specified for different source sets
#KT-16698 Fixed
2017-03-09 23:06:28 +03:00
Alexey Sedunov
0e583aa929 Kotlin Facet: Update Gradle import test data to use 1.1.0 plugin 2017-03-09 23:06:23 +03:00
Alexey Sedunov
278cc71c4a Kotlin Facet: Reuse configuration serialization in JPS (previous implementation is not usable after configuration refactoring) 2017-03-09 23:06:18 +03:00
Alexey Sedunov
641a9a7153 Kotlin Facet: Get rid of duplicating data in facet configuration 2017-03-09 23:06:12 +03:00
Alexey Sedunov
19ea18a340 Kotlin Facet: Correctly enable/disable "output directory" field when changing "Use project settings" option
#KT-16317 Fixed
2017-03-09 22:48:44 +03:00
Dmitry Jemerov
01a9d9a284 Support lazy conversion of parent chain; correctly check expected class 2017-03-09 17:07:43 +01:00
Dmitry Jemerov
8c3936a0ee Update to UAST 0.12 2017-03-09 17:07:43 +01:00
Simon Ogorodnik
3bf7223448 Internal Kotlin packages now should be completable in parent packages
Internal packages which are hard-excluded from completion and
 imports now should be visible there if file package are parent of
 excluded one
 e.g kotlin.jvm.internal.* now visible from kotlin and kotlin.jvm
 #KT-16214 fixed
2017-03-09 19:05:10 +03:00
Dmitry Petrov
27bf51c73f All multifile class tests should have 'TARGET_BACKEND: JVM' directive. 2017-03-09 17:22:28 +03:00
Dmitry Petrov
6a68eb218f KT-16077 Redundant private getter for private var in a class within a JvmMultifileClass annotated file 2017-03-09 17:22:28 +03:00
Dmitry Jemerov
c9df227fef Add more tests for coroutines; use higher-level API to check that changes have been applied 2017-03-09 13:57:45 +01:00
Dmitry Jemerov
73a2c8c436 Test quickfixes for updating language/API version and coroutine support in Gradle projects 2017-03-09 13:41:57 +01:00
Dmitry Jemerov
5d461ec6df Support updating language/API level specified with compact options 2017-03-09 13:41:57 +01:00
Dmitry Jemerov
4261880340 Add test for enabling coroutines/bumping language level, fix several breakages 2017-03-09 13:41:57 +01:00
Sergey Igushkin
999ef51653 Added gradle-plugins properties with fqnames
Added .property files to make the plugins available by fqnames in
order to publish them to Gradle Plugin Portal.

#KT-5756

(cherry picked from commit 991de64)
2017-03-09 14:13:40 +03:00
Dmitry Jemerov
cbccb68948 Fix logic for searching inner classes in LazyResolveBasedCache.findInPackageFragments()
#KT-14058 Fixed
2017-03-09 11:47:21 +01:00
Alexander Udalov
9f2ce3c521 Refactor synthesized invokes creation in resolution
Instead of verifying that the container of an 'invoke' is a
FunctionClassDescriptor instance, make sure that it's a function class
checking its FQ name instead (classId + isBuiltinFunctionClass calls).
This makes sure that we will create synthesized invokes in a setting
where function classes are not FunctionClassDescriptor instances
synthesized by the compiler, but ordinary classes from sources or
binaries as well, as is going to be the case in kotlin-native
2017-03-09 11:29:39 +03:00
Dmitry Petrov
d188de3086 KT-6014 Wrong ABSTRACT_MEMBER_NOT_IMPLEMENTED for toString implemented by delegation
Members declared in interface or overriding members declared in super-interfaces
can be implemented by delegation even if they override members declared in super-class
(NB for interface this can be only 'kotlin.Any').
2017-03-09 09:38:48 +03:00
Mikhail Glukhikh
5e8afd26e1 Do not run write actions from J2K #KT-16714 Fixed
Also #EA-97363 Fixed
2017-03-09 09:37:35 +03:00
Dmitry Petrov
f950ff4b8f 'ConstructorDescriptor#getConstructedClass()' should be used to obtain a descriptor for constructed class
(it can be different from 'getContainingDeclaration()' in case of type alias constructor).

KT-15109 Subclass from a type alias with named parameter in constructor will produce compiler exception
KT-15192 Compiler crashes on certain companion objects: "Error generating constructors of class Companion with kind IMPLEMENTATION"
2017-03-09 09:23:38 +03:00
Dmitry Petrov
9a2c9ed30e KT-13342 Unqualified super call should not resolve to a method of supertype overridden in another supertype 2017-03-09 09:16:21 +03:00
Dmitry Jemerov
954c1d853d Correctly locate build.gradle for modules created from source sets
(cherry picked from commit ecce92d)
2017-03-08 15:08:41 +01:00
Dmitry Jemerov
a2f7808ab1 Don't check Java version in LauncherScriptTest 2017-03-08 14:07:47 +01:00
Dmitry Jemerov
263cf85c5c Fix project leak in IdeReplExecutionTest 2017-03-08 13:47:09 +01:00
Dmitry Petrov
11caa03427 KT-16713 Insufficient maximum stack size
1. Analyze method node with fake jumps for loops to make sure that
all instructions reachable only through break/continue jumps are processed.
2. Fix stack for break/continue jumps.
3. Drop fake jumps for loops, analyze method node again.
4. Fix stack for try/catch and beforeInline.
2017-03-08 09:56:08 +01:00
Mikhail Glukhikh
80063b6f91 Quick-fix for DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE added #KT-15966 Fixed 2017-03-07 19:06:16 +03:00
Ilya Gorbunov
b83b534374 Add missing SinceKotlin to IntStream.toList. 2017-03-07 18:22:11 +03:00
Ilya Gorbunov
c038d3e9a3 Mark all api in kotlin.reflect.full package with SinceKotlin(1.1), since it actually appeared in that package only in 1.1. #KT-16557 Fixed.
It doesn't matter that some functions were since 1.0 in the old package.
2017-03-07 18:22:11 +03:00
Kirill Rakhman
646f50dd66 Extract method refactoring should order parameters by first usage
Fixes #KT-16198
2017-03-07 18:10:02 +03:00
Ilya Gorbunov
1296c5444b Fix warning that failed maven plugin smoke test. 2017-03-07 13:56:11 +03:00
Ilya Gorbunov
61e8848aa2 Add samples for sequence building API. 2017-03-07 13:32:39 +03:00
Ilya Gorbunov
a04e6de047 Add groupingBy and eachCount sample. 2017-03-07 13:31:44 +03:00
Ilya Gorbunov
75ae42121b Improve sample comments.
Improve sample for lastIndex property.
2017-03-07 13:31:44 +03:00
Mikhail Zarechenskiy
578dd1dc42 Update Changelog for Kotlin 1.1.1-RC 2017-03-07 12:12:04 +03:00
Dmitry Petrov
d096f1d381 'while' and 'do-while' loop generator fixes.
Generate 'do-while' loop body as IrComposite, because variables declared
in loop body should be visible in loop condition.
Wrap 'do-while' loop in IrBlock so that variables declared in loop body
are not visible outside of the loop.

Generate 'while' and 'do-while' loops as expressions of type Unit.
2017-03-07 11:56:52 +03:00
Dmitry Petrov
cb61c358ea Always generate primitive boolean constants as expressions of type 'kotlin.Boolean'. 2017-03-07 11:56:52 +03:00
Dmitry Petrov
1bbbc1ca1c KT-16684 hashCode doesn't check data class property value of generic type for null 2017-03-07 11:56:52 +03:00
Dmitry Petrov
68fab55251 Minor: cleanup unused imports 2017-03-07 11:56:52 +03:00
Dmitry Petrov
6bc6c1b6cc KT-16671 Calls to members imported from objects should be desugared in PSI2IR 2017-03-07 11:56:52 +03:00
Dmitry Petrov
4ba8268a29 KT-16669 Exception in PSI2IR on type alias constructor in supertypes list 2017-03-07 11:56:52 +03:00
Dmitry Petrov
e4683a1e9f KT-16666 IMPLICIT_INTEGER_COERCION expression should have non-nullable type 2017-03-07 11:56:52 +03:00
Dmitry Petrov
8c32719f3d Render 'type' for IrTypeOperatorCall expressions, update testData. 2017-03-07 11:56:52 +03:00
Dmitry Petrov
b3aeddac85 Refactor: generalize postfix order transformation in InsertImplicitCasts 2017-03-07 11:56:52 +03:00
Dmitry Petrov
8e8f83656f KT-16618 IMPLICIT_INTEGER_COERCION isn't generated for global properties and default parameters 2017-03-07 11:56:52 +03:00
Sergey Igushkin
ee6aae7219 Enabled incremental compilation by default in Gradle plugin.
#KT-16546 Fixed

(cherry picked from commit 06715c5)
2017-03-07 11:32:26 +03:00
Alexey Andreev
ef38761dc2 JS: unmute now passing tests and mute test that passed by accident. 2017-03-07 10:46:09 +03:00
Alexey Andreev
a6ca2906d8 JS: add tests for reflection against external classes 2017-03-07 10:46:08 +03:00
Alexey Andreev
723c9be5a0 JS: fix class literal expression with primitive classes. See KT-16545 2017-03-07 10:46:08 +03:00
Alexey Andreev
8567db10b5 JS: fix coroutine transformation of callable references to local functions. See KT-16164 2017-03-07 10:46:07 +03:00
Dmitry Petrov
18fb70b32f Potential fix for KT-16673
See also:
http://stackoverflow.com/questions/42571812/unsupportedoperationexception-while-building-a-kotlin-project-in-idea

'original' for SamAdapterFunctionScope.MyFunctionDescriptor#doSubstitute should exactly match 'this.original',
so we can just provide it by default in SamAdapterFunctionScope.MyFunctionDescriptor#newCopyBuilder.
2017-03-06 22:00:09 +03:00
Dmitry Jemerov
268f7b715c "Configure Kotlin plugin updates" shows 1.2 and doesn't show 1.0.x 2017-03-06 19:50:58 +01:00
Ilya Chernikov
50e7973fc0 Implement verification workaround for annotation-like class InvalidScriptResolverAnnotation
fixes #KT-16621
2017-03-06 16:31:52 +01:00
Sergey Mashkov
243f718193 EA-88059 - assert: CompositeElement.addChild
ensure parent element for anchor elements so we never try to insert at wrong place
2017-03-06 17:34:36 +03:00
Sergey Mashkov
4637dcde33 EA-86479 - ISE: PomFile.<init>
don't apply any inspections for inappropriate pom files
2017-03-06 17:34:35 +03:00
Mikhael Bogdanov
ff9fe85507 Fix for KT-16614: Report inability to inline 1.8 bytecode into 1.6 bytecode as an error, no as an exception 2017-03-06 15:15:22 +01:00
Vyacheslav Gerasimov
5e4459f41d Fix broken MultiFileHighlightingTest
Android resource folding builder should not run in non-Android projects
2017-03-06 14:31:01 +03:00
Alexander Udalov
0111c4d581 Allow references to nested class constructors in objects in LV = 1.0
#KT-16598 Fixed
2017-03-06 11:03:24 +03:00
Alexander Udalov
7c22113c34 Refactor serialization of package FQ name extension
Instead of requiring to pass it in SerializerExtensionBase's
constructor, pass it always in serializePackage. This is more
straightforward and helps in a situation where one SerializerExtension
instance is used for the whole module, not one per-package
2017-03-06 11:03:24 +03:00
Kirill Rakhman
c952e26cbb Fix NPE caused by Rename Refactoring of backing field when caret is after the last character
#KT-16605 Fixed
2017-03-06 11:01:38 +03:00
Kirill Rakhman
1bad04db50 Fix Can't rename implicit lambda parameter 'it' when caret is placed right after the last character
#KT-14401 Fixed
2017-03-06 11:01:38 +03:00
Ilya Chernikov
e3391175d9 Rewrite parallel daemon start test to make it tougher but more robust 2017-03-05 11:29:54 +01:00
Anton Bannykh
4c6b9b695c JS: mute some tests with extension functions in external declarations 2017-03-03 21:39:40 +03:00
Anton Bannykh
fcffd190d0 JS: prohibited extension function arguments in external functions; removed extension receiver in jQuery declarations. 2017-03-03 20:37:59 +03:00
Sergey Igushkin
73e94ffde0 Added a test for the fix of KT-16434.
(cherry picked from commit 5a6d06f)
2017-03-03 18:04:23 +03:00
Sergey Igushkin
6605ba80e7 Fix for androidTest variants of Android Gradle build.
Added a workaround reflection call to TaskManager to create a
javac task since it is missing for androidTest variants with jack.
Added source configuration with the tested variant to make
the tested sources visible to the compiler.

#KT-16434 Fixed

(cherry picked from commit 84efd05)
2017-03-03 18:04:12 +03:00
Mikhail Glukhikh
0432e2e947 Quick-fix to add noinline to parameter with suspend function type + AddInlineModifierFix refactoring #KT-16074 Fixed 2017-03-03 17:28:37 +03:00
Mikhail Glukhikh
d9710ea4ff #EA-97027 Fixed 2017-03-03 17:28:35 +03:00
Mikhail Glukhikh
8965bb8977 Navigation: new icons for header <---> impl #KT-15842 Fixed 2017-03-03 17:28:34 +03:00
Vyacheslav Gerasimov
1376c8f8cf Implement quickfixes for Android Lint api issues
#KT-16624 Fixed
#KT-16625 Fixed
#KT-14947 Fixed
2017-03-03 16:22:36 +03:00
Vyacheslav Gerasimov
a907ec92b5 Implement Android resource reference folding
#KT-15451 Fixed
2017-03-03 16:18:20 +03:00
Vyacheslav Gerasimov
39010ab847 Fix broken isReferenceTo checking code for Android extensions
#KT-16132 Fixed
2017-03-03 16:17:52 +03:00
Alexander Udalov
25c1828288 JS: write and load pre-release flag on binaries 2017-03-03 13:33:51 +03:00
Alexander Udalov
de8dd37e44 Change DeserializedContainerSource.presentableFqName to String
To allow outputting something other than "Class 'XXX'" in the diagnostic
message for declarations deserialized from JS
2017-03-03 13:33:51 +03:00
Alexander Udalov
f120865350 Combine cls stub builders for built-ins and JS 2017-03-03 13:33:51 +03:00
Alexander Udalov
297eb952bc Extract common parts of built-ins and JS decompilers 2017-03-03 13:33:51 +03:00
Alexander Udalov
b52b90c182 Extract serialization of packageFqName extension to SerializerExtensionBase 2017-03-03 13:33:51 +03:00
Alexander Udalov
4e91dadfab Combine decompiler deserializers for built-ins and JS 2017-03-03 13:33:50 +03:00
Alexander Udalov
bafa0ec1ee Minor, don't throw exception on empty proto message 2017-03-03 13:33:50 +03:00
Alexander Udalov
5a00a97cf1 Extract common parts from deserialization of built-ins and JS 2017-03-03 13:33:50 +03:00
Alexander Udalov
3cb8f1ab20 Drop BuiltIns protobuf message, use ProtoBuf.PackageFragment instead 2017-03-03 13:33:50 +03:00
Alexander Udalov
a36e457c12 Introduce PackageFragment protobuf message for kjsm/builtins/common metadata 2017-03-03 13:33:50 +03:00
Alexander Udalov
2b1b1fb0d4 Merge VirtualFileKotlinClassFinder into VirtualFileFinder
VirtualFileKotlinClassFinder was the only direct subclass of VirtualFileFinder
2017-03-03 13:33:50 +03:00
Alexander Udalov
abb5bc6aba Simplify VirtualFileFinder and their factories' hierarchy
Since there's no JsVirtualFileFinder anymore, inline JvmVirtualFileFinder into
VirtualFileFinder and drop "Jvm" prefix everywhere
2017-03-03 13:33:50 +03:00
Alexander Udalov
ee0874a26d Drop JsVirtualFileFinder and its factory, refactor nearby
The only remaining usage was in KotlinRuntimeLibraryUtil.kt where we only
needed to check whether there's at least one file in a given package indexed by
KotlinJavaScriptMetaFileIndex. Move that logic to a public extension, drop
everything else
2017-03-03 13:33:50 +03:00
Alexander Udalov
67699bf17e Rename metadata version index and its subclasses 2017-03-03 13:33:50 +03:00
Alexander Udalov
57877bb007 Add default value to js_code_binary_version in js.proto
By default, assume the version is 1.0.0
2017-03-03 13:33:49 +03:00
Mikhael Bogdanov
a03ed6f742 Fix for KT-16581: VerifyError when calling default value parameter with jvm-target 1.8
#KT-16581 Fixed
2017-03-03 11:21:42 +01:00
Ilya Chernikov
ffe3453937 Do not pollute IDEA log with fake script dependencies 2017-03-03 10:59:28 +01:00
Mikhail Glukhikh
3060ecc066 Minor build fix: "Convert to apply" is now applicable only with 2+ calls with the same receiver 2017-03-03 11:10:01 +03:00
Dmitry Petrov
634d9834de Wrong receiver is generated for variable-as-function call on object.
Move 'generateExpressionForReferencedDescriptor' to CallGenerator,
use it in 'generateCall',
add PSI-free versions of some utility methods so that call elements can
be generated when we're already deep in ResolvedCall generation
and have forgotten about PSI.
2017-03-03 10:15:59 +03:00
Mikhail Zarechenskiy
d573962259 Add test for class delegation with private constructor
#KT-16583 Obsolete
2017-03-02 18:34:59 +03:00
Mikhail Zarechenskiy
e2dcec62d3 Fix access to top-level declarations inside anonymous initializer
#KT-16583 Fixed
2017-03-02 18:34:51 +03:00
shiraji
0e5603f644 Implement an intention converting several calls with same receiver to with/apply/run #KT-12183 Fixed 2017-03-02 16:56:56 +03:00
shiraji
c2e5fc5215 Move KtDotQualifiedExpression.deleteFirstReceiver to Utils.kt 2017-03-02 16:56:53 +03:00
Alexander Udalov
39d0cd7237 Test that all Kotlin versions in the project are consistent
There are two different tests: the one that checks that all versions are
consistent (but not equal, because some versions are major.minor.patch,
but some only major.minor), and the one that checks that versions of all
subprojects of the Maven projects are exactly equal (1.1-SNAPSHOT
currently)

 #KT-16455 Fixed
2017-03-02 16:36:51 +03:00
Denis Zharkov
6fb83c2ba3 Force wrapping java classes from annotation methods into KClasses
Before this change such wrapping happened only during coercion,
i.e. when a call-site expected a KClass instance.

But when call-site expects Any, for example, no wrapping happened,
and raw j.l.Class instance was left on stack.

The solution is to put wrapping code closer to generation of annotation's
method call itself to guarantee that necessary wrapping will happen.

 #KT-9453 Fixed
2017-03-02 15:19:09 +03:00
Denis Zharkov
415c3d57af Fix substitutor for synthetic SAM adapters
When synthetic member comes not from the receiver type itself,
but from one of its supertypes it doesn't make sense to subsitute
the member with receiver type, we should obtain relevant supertype
and use it instead.

 #KT-16578 Fixed
2017-03-02 15:06:59 +03:00
Anton Bannykh
9e5ecc11b7 JS: fixed Double.NaN behaviour (KT-13610). 2017-03-02 14:29:50 +03:00
Dmitry Petrov
f636ab21f8 Use proper descriptor for (generic) property assignment.
Insert IMPLICIT_INTEGER_COERCION only if Int is coerced to an integer type.
2017-03-02 14:25:58 +03:00
Dmitry Petrov
97fbbc74e6 KT-16440 ClassConstructorDescriptorImpl has null returnType
Set constructor return type in FunctionDescriptorResolver#createConstructorDescriptor
(it seems to be the only place where ClassConstructorDescriptorImpl#initialize(...)
is called, but returnType is not set).
2017-03-02 14:25:58 +03:00
Dmitry Petrov
dc1d92855d KT-16438 Strange dispatch receiver for descriptors of delegated members
Provide proper dispatch receiver parameter for delegated members.
Use dispatch receiver parameter for delegated members in IR generation
for delegated member body (and check that the receiver has corresponding type).
2017-03-02 14:25:58 +03:00
Dmitry Petrov
c92f118e5e Refactoring: introduce CopyBuilder for CallableMemberDescriptor and PropertyDescriptor.
Allow providing new dispatchReceiverParameter via CopyBuilder
(required for proper dispatch receiver for delegates).
2017-03-02 14:25:58 +03:00
Dmitry Petrov
9baaf607a3 KT-16566 Support destructuring declarations for lambda parameter in psi2ir 2017-03-02 14:25:58 +03:00
Dmitry Petrov
c226707a80 KT-16554 Local function with default arguments have no IR elements for them 2017-03-02 14:25:58 +03:00
Igor Chevdar
ab3681e164 Package level delegated properties have no dispatch receiver. 2017-03-02 12:33:01 +03:00
Igor Chevdar
3ef612f05a Added dispatch receiver to delegation implementing property 2017-03-02 12:33:01 +03:00
Simon Ogorodnik
6dd75f697a Fix Show implementation to show inheritance through type-aliases
Show implementation(Ctrl-Hover) now should show classes which inherit such class through type-alias
 #KT-15200 fixed
2017-03-01 23:05:19 +03:00
Yan Zhulanow
593fbadc98 Force using the 'kotlin-stdlib-jre7' artifact when configuring Android modules with JDK >= 1.8 as Dex can't process our 'kotlin-stdlib-jre8' artifact.
This fixes KT-16530: Configure Kotlin in Project inserts dependency to kotlin-stdlib-jre8 in Android projects.
2017-03-01 18:50:22 +03:00
Yan Zhulanow
060095d39f Remove kotlin-annotation-processing artifact from the serialized compiler options. It is unused in kapt3 (or if no annotation processor dependencies are provided) but is still imported into the IDEA module files. This leads to compilation error due to the plugin incompatibility.
Incompatibility reason: kotlin-annotation-processing has references to the shaded intellij-core, so, being provided to the unshaded kotlinc from the Kotlin plugin, it throws the AbstractMethodError.

This fixes #KT-16184.
2017-03-01 18:50:22 +03:00
Kirill Rakhman
2506bb6673 Inspection checking that destructuring variable name matches the name of different component #KT-12004 Fixed 2017-03-01 18:24:48 +03:00
Dmitry Jemerov
af7de9a0c5 Warn when running the compiler under Java 6 or 7
(cherry picked from commit 5537800)

(cherry picked from commit 5614874)
2017-03-01 16:21:57 +01:00
Simon Ogorodnik
000da2f6d0 Fix of <ERROR CLASS>-es pointing to public TypeAliases 2017-03-01 16:09:24 +01:00
Dmitry Jemerov
78b4cbdb69 Don't generate documentation for option that doesn't work in Gradle 2017-03-01 16:09:23 +01:00
Alexey Andreev
0c0e0aab09 JS: add some docs to declarations related to interop 2017-03-01 16:09:21 +01:00
Dmitry Jemerov
322379e6ae Assorted stdlib KDocs 2017-03-01 16:09:01 +01:00
Dmitry Jemerov
1d86bd5610 Build multiplatform stdlib docs 2017-03-01 16:08:38 +01:00
Dmitry Jemerov
adc937c57d Extract separate target for preprocessing JS stdlib sources 2017-03-01 16:08:28 +01:00
Kirill Rakhman
8d425a6f94 Add intention to add missing components to destructuring assignment #KT-16258 Fixed 2017-03-01 18:00:55 +03:00
Mikhael Bogdanov
4d47c0fd63 Partial fix for KT-16193: Incremental compilation generates invalid bytecode for crossinlined functions; avoid IllegalAccessError 2017-03-01 14:45:11 +01:00
Alexander Udalov
3ad4f18e1a Update grammar to Kotlin 1.1
Also drop obsolete comments and inline some trivial rules
2017-03-01 14:50:36 +03:00
Mikhail Zarechenskiy
875fdef917 Add tests for obsolete issues
#KT-15913 Obsolete
 #KT-12248 Obsolete
2017-03-01 14:07:09 +03:00
Anton Bannykh
318014e4ab Test vararg with Java behaviour only for JVM backends 2017-03-01 13:58:57 +03:00
Mikhail Glukhikh
91cd590395 Change log: note about javaClass added 2017-03-01 10:14:57 +03:00
Denis Zharkov
a7fc32c8da Add diagnostic on calling inner classes constructors without receiver
Otherwise there will be just an unresolved reference that doesn't give
any useful information

 #KT-8959 Fixed
2017-03-01 09:59:01 +03:00
Denis Zharkov
1e0ae04aba Minor. Convert if to when 2017-03-01 09:59:00 +03:00
Denis Zharkov
b5a8ffaddc Fix resolution of callable references
When there is unsuccessful (e.g invisible) result of one kind (static/non-static)
and there is a successful candidate for another kind, choose the latter one.

Note, that we have to postpone commiting trace until we choose one of the results,
otherwise errors of unsuccessful results are reported

TODO: Maybe it makes sense to report all results when all of them are
unsuccessful (NONE_APPLICABLE or something like this)

 #KT-16278 Fixed
2017-03-01 09:59:00 +03:00
Dmitry Petrov
dd61a5b2c6 KT-16553 Underscore variable values shall not be evaluated
Do not generate 'componentN' calls for '_' in destructuring assignment.
2017-03-01 09:25:38 +03:00
Dmitry Petrov
63b16e14d8 KT-16536 Wrong IR generated for '++x'
Make psi2ir confirm to JVM BE behavior for prefix increment/decrement.
TODO reconsider after design decision (in 1.2?).
2017-03-01 09:25:38 +03:00
Dmitry Petrov
885f397cdd KT-16535 'provideDelegate' convention is not supported in IR
Implement provideDelegate convention support.
NB delegate type now depends on 'provideDelegate' convention resolution.
2017-03-01 09:25:38 +03:00
Dmitry Petrov
6046b25f56 Minor: silence that irritating KT-14030 2017-03-01 09:25:38 +03:00
Dmitry Petrov
045a12ddc6 Minor: constructor IrExpressionBodyImpl(IrExpression) 2017-03-01 09:25:38 +03:00
Dmitry Petrov
e66c2621af KT-16436 Incorrect primitive constants handling
Expression '1.unaryMinus()' is resolved as Int::unaryMinus call with Int receiver.
However, this expression is implicitly coerced to a different integral type (Byte, Short, Long)
based on results of constant evaluation.

Introduce IMPLICIT_INTEGER_COERCION type operator to handle such cases.

TODO: should we use it for simple constant expressions like '1' and '-1'?
2017-03-01 09:25:38 +03:00
Dmitry Petrov
d0134f2c64 KT-16437 Incorrect type inference for some when coerced to Unit
If the result of 'when' is not used in an expression,
this 'when' expression has type 'Unit' despite of whatever FE has inferred.
2017-03-01 09:25:38 +03:00
Dmitry Petrov
e2e57e5b6d KT-16439 Generated methods of data classes have no expression for default arguments
Provide default argument expressions for generated 'copy' declaration.
2017-03-01 09:25:38 +03:00
Dmitry Petrov
0f1f354ba6 KT-16486 Strange IR for delegated members
Delegated implementations should refer to delegate field:
  $this: GET_FIELD <delegate_field> ...
    receiver: <this_for_containing_class>
2017-03-01 09:25:38 +03:00
Alexander Udalov
abbbdb5771 Update KotlinVersion.CURRENT to 1.1.2 2017-02-28 20:24:33 +03:00
Alexander Udalov
559da842c0 Clear reflection caches in black box codegen tests
To prevent tests from altering outcomes of the subsequent tests.

Also expose the clearCaches method (in the internal class
ReflectionFactoryImpl) so that it can be used in other places in similar
circumstances
2017-02-28 20:19:58 +03:00
Alexander Udalov
e19c1b5364 Drop MockTypeAliasDescriptor, use MockClassDescriptor instead
It's irrelevant whether the non-found classifier is a class or a
typealias
2017-02-28 20:19:58 +03:00
Alexander Udalov
12b48f86e7 Do not load error classes in ReflectionTypes
Previously ReflectionTypes.find returned an error class in case a class
is not found in the module dependencies. The problem with this approach
is that each call site should call ErrorUtils.isError on the result and
report an error if needed, in order to stop this type from reaching the
codegen, which can't handle error types.

Now we create a MockClassDescriptor instance instead. It's not an error
class, so it'll be handled correctly in the codegen. Also its scope is
empty and errors are reported on any non-trivial usage (see
MissingDependencyClassChecker), so this approach is not worse than error
classes

 #KT-16484 Fixed
2017-02-28 20:19:58 +03:00
Alexander Udalov
794cc1e3be Refactor API of NotFoundClasses
Move deserialization-related stuff to TypeDeserializer, because it's
going to be used in other places besides deserialization
2017-02-28 20:19:58 +03:00
Alexander Udalov
86994f81c3 Refactor ClassId.getOuterClassId, make it nullable 2017-02-28 20:19:57 +03:00
Mikhael Bogdanov
21de67cac1 Fix for KT-16532: Kotlin 1.1 RC - Android cross-inline synchronized won't run
Finnaly markers are used only for non-local return processing and are removed after inlining  to non-inline functions, same deletion should be performed on inlining to anonymous objects

 #KT-16532 Fixed
2017-02-28 15:40:04 +01:00
Alexey Sedunov
387c91f957 Kotlin Facet: Do not concat "additional argument" string as configuration gets duplicated
KT-16548 Fixed
2017-02-28 16:07:58 +03:00
Anton Bannykh
6608e97d35 JPS JS: simplified the code and added tests for the missing meta.js case (e.g. empty sourceroot; fixed by yole in 00ed0248d9a23701dbef52da02259d174a9999e7) 2017-02-28 16:05:16 +03:00
Anton Bannykh
2d9392aad4 JS: fixed callable reference to a class constructor within object (KT-16411). 2017-02-28 15:55:50 +03:00
Mikhail Glukhikh
6ed3672f8d Change log for 1.1 (release)
(cherry picked from commit afd6e0d)
2017-02-28 11:46:25 +03:00
Denis Zharkov
ecec87cbc7 Refine signature calculation for methods with default parameters
The problem was that he number of mask parameters for defaults when
generating methods declaration was being calculated upon resulting signature
(with additional parameters: extension receivers, enum name/ordinal),
while on call-sites the masks number was calculated by the arguments number
in resolved call, i.e. by the number of real value parameters.

And because of the additional synthetic parameters (like enum.ordinal) these
two numbers could be different.

The solution is just to use value parameters number in both places.
Note, that we only count value parameters from the original sourse
declaration, ignoring synthetic ones generated by backend (e.g.
Continuation for suspend functions)

 #KT-14565 Fixed
2017-02-28 10:42:07 +03:00
Denis Zharkov
9e03b712de Use flexible upper bound of parameter's type for vararg argument
See the issue and the test. The problem was that when generating
call to `foo` method in member scope of `AT<*>` its resulting descriptor
after substitution and approximation was: fun foo(x: Nothing..Array<out Nothing>).

This signature is correct, but when using this parameter type
for generating a vararg argument the assertion is violated that
the type of the argument must be an array
(by default we're using lower flexible bound everywhere)

The solution is using upper bound for flexible types that should
always have a form of Array<out T> for varargs (even for such corner cases)
both for Kotlin and Java declarations.

 #KT-14607 Fixed
2017-02-28 10:40:54 +03:00
Alexey Sedunov
14dad61fe5 Kotlin Facet: Import more configuration options from Maven
(cherry picked from commit dca696f)
2017-02-28 03:06:54 +03:00
Alexey Sedunov
90c2b14051 Kotlin Facet: Import Maven option specified in <jvmTarget> element
#KT-16329 In Progress
2017-02-28 03:05:13 +03:00
Nikolay Krasko
b9b4cce293 Set JVM target from facet settings on compiler configuration creation
Otherwise analyse in IDE is perfomed under default JVM target and wrong
diagnostics are reported.

 #KT-16329 In Progress
2017-02-28 02:32:59 +03:00
Roman Elizarov
266d7c15fe Documentation for createCoroutine/createCoroutineUnchecked 2017-02-27 16:48:24 +03:00
Nikolay Krasko
f0be88fc07 Use doResume name for suspend lambdas context (KT-16481)
#KT-16481 Fixed
2017-02-27 14:49:13 +03:00
Nikolay Krasko
dffbe0f707 Count JVM class name for inlined function from base declaration
Drop code with naive removing all anonymous classes.
Breakpoints now works when inline call is in anonymous call.
2017-02-27 14:49:12 +03:00
Nikolay Krasko
cd92e3fc98 Refactoring: use constants instead of string literals 2017-02-27 14:49:11 +03:00
Ilya Chernikov
fa5728b288 Use Void instead of Unit in RMI calls, should fix EA-82064
("Could not initialize class Kotlin.Unit")

(cherry picked from commit b3a1311)
2017-02-24 16:58:25 +01:00
Ilya Chernikov
00e8dfe1be Use sessions with connection to eliminate async shutdown problems
(cherry picked from commit 78d334b)
2017-02-24 16:58:25 +01:00
Ilya Chernikov
4202bde550 Make daemon connection more reliable by retrying on certain exceptions
(cherry picked from commit 74a0711)
2017-02-24 16:58:25 +01:00
Ilya Chernikov
c7a2422314 minor: Make parallel daemong start test less demanding 2017-02-24 16:58:25 +01:00
Ilya Chernikov
6d9ecc60ef Skip metadata version check in repl, improve JSR 223 template compatibility 2017-02-24 16:58:25 +01:00
Ilya Chernikov
a16f412b48 Add eval in eval benchmark tests 2017-02-24 16:58:25 +01:00
Ilya Chernikov
1ae95853e7 Fix merging errors 2017-02-24 16:58:25 +01:00
Ilya Chernikov
d3682b7f7d Implement JSR 223 script template with eval functions, some fixes 2017-02-24 16:58:25 +01:00
Ilya Chernikov
63aae56b11 Get rid of eval on daemon completely, fixes also JSR 223 examples 2017-02-24 16:58:24 +01:00
Ilya Chernikov
a3a782613a Cleanup 2017-02-24 16:58:24 +01:00
Ilya Chernikov
1032f0d39c Fix java 8 repl tests 2017-02-24 16:58:24 +01:00
Ilya Chernikov
b9469a9308 Fix script-util after changes in repl infrastruct 2017-02-24 16:58:24 +01:00
Ilya Chernikov
75234701c7 Fix remote repl state facade 2017-02-24 16:58:24 +01:00
Ilya Chernikov
b23911fd59 Reintroduce history check between compile and eval, place generation into code line and id 2017-02-24 16:58:24 +01:00
Ilya Chernikov
7b2ea001c1 Fix state conversion, fix tests 2017-02-24 16:58:24 +01:00
Ilya Chernikov
c5bc58ad32 Implement remote part of the new repl state handling 2017-02-24 16:58:24 +01:00
Ilya Chernikov
f9dedab8c8 Extract repl state as a separate object 2017-02-24 16:58:24 +01:00
Anton Bannykh
3eb5b3e08c JS: changed BoxedChar visibility to internal 2017-02-24 13:46:29 +03:00
Dmitry Jemerov
5c9f0df256 Download specific build of IJ 162, not a snapshot 2017-02-24 11:19:43 +01:00
Nikolay Krasko
6b62686019 Add blank lines tab to Kotlin code style UI with two basic options
KEEP_BLANK_LINES_IN_CODE
KEEP_BLANK_LINES_IN_DECLARATIONS

#KT-15504 In Progress
2017-02-22 20:13:28 +03:00
Nikolay Krasko
bc90d52873 Minor: remove warnings in KotlinSpacingBuilder.kt 2017-02-22 20:13:24 +03:00
Nikolay Krasko
6a4590839c Don't merge two lines in formatter after line comment (KT-16032)
#KT-16032 Fixed
2017-02-22 20:12:19 +03:00
Nikolay Krasko
20f92c6200 Use own kotlin settings for spacing instead of default set
Mostly affected by settings:
- KEEP_LINE_BREAKS,
- KEEP_BLANK_LINES_IN_DECLARATIONS
- KEEP_BLANK_LINES_IN_CODE

Allow settings KEEP_LINE_BREAKS in UI.
2017-02-22 20:04:34 +03:00
Nikolay Krasko
5ed5f8f048 Minor: reuse DO_RESUME_METHOD_NAME constant instead of literal 2017-02-22 19:58:50 +03:00
Alexander Udalov
a9678010a8 Invert LanguageFeature responsible for warning on coroutines
The problem was that LanguageVersionSettingsImpl.DEFAULT did not have
"WarnOnCoroutines" as a feature and so it was manually added to the settings,
but only in two places: in the compiler and in the IDE
2017-02-22 18:55:48 +03:00
Dmitry Jemerov
e3dab96715 Add Trove4j license 2017-02-22 16:04:33 +01:00
Ilya Gorbunov
6e8f227121 Drop ERROR deprecations in JS library that were introduced in 1.1-rc 2017-02-22 17:28:02 +03:00
Ilya Gorbunov
b393c66426 Drop ERROR deprecations from kotlin-reflect. 2017-02-22 17:28:02 +03:00
Ilya Gorbunov
c0c01d6e49 Drop HIDDEN deprecations from kotlin-stdlib. 2017-02-22 17:28:02 +03:00
Ilya Gorbunov
8e951dee16 Drop remaining ERROR deprecations from kotlin-stdlib-js.
Leave only `native`, `parseInt`, `parseFloat` and `noImpl`.
2017-02-22 17:28:02 +03:00
Ilya Gorbunov
eebb820060 Do not refer to java packages in common completion tests 2017-02-22 17:28:02 +03:00
Ilya Gorbunov
3cea5c4510 Drop entire java.util package from kotlin-stdlib-js
#KT-6561 Fixed
2017-02-22 17:28:02 +03:00
Ilya Gorbunov
5867d27fb7 [Standard Library] Take the javaClass deprecation back as its replacement is often inconvenient. 2017-02-22 17:27:20 +03:00
Alexander Udalov
d124912c91 Specify language / API version in .idea/kotlinc.xml 2017-02-22 14:45:57 +03:00
Anton Bannykh
909d83c3af JS: Force Rhino to load files using UTF8 encoding. Fixes failing kt14597 on windows agents. 2017-02-22 14:39:46 +03:00
Alexey Andreev
66f5a12cc4 JS: fix translation of && and || operators when their RHS declare temporary variables. See KT-16350 2017-02-22 11:10:07 +03:00
Dmitry Jemerov
c6bfb02754 Move JsAnalyzerFacade to ide-common module to enable its use in Dokka 2017-02-21 18:39:21 +01:00
Stanislav Erokhin
0a24bf1613 Fix type deserialization for suspend function types which was written by pre-release compiler.
Notes: if arity == 0, it means that type was `suspend () -> String` => arguments.size == 1, and it means that SuspendFunction0 has only one type argument and it is return type.
2017-02-21 17:26:07 +03:00
Stanislav Erokhin
81df7645e0 Fix potential CCE -- use unwrappedType after instanceof check. 2017-02-21 17:19:50 +03:00
Mikhael Bogdanov
d24ebf711b Fix for KT-16441: NoSuchFieldError: $$delegatedProperties when delegating through provideDelegate in companion object
#KT-16441 Fixed
2017-02-21 13:01:40 +01:00
Mikhael Bogdanov
a8625b632d Fix for KT-16411, KT-16412: Exception from compiler when try call SAM constructor where argument is callable reference to nested class inside object
#Fixed KT-16411
  #Fixed KT-16412
2017-02-21 11:40:25 +01:00
Denis Zharkov
85f9e2e47b Fix CCE in generated code that happens when comparing boxed chars
The problem was that when obtaining char from the wrapper,
codegen used int as expected type that led
to a ClassCastException: java.lang.Character cannot be cast to java.lang.Number

The solution is using coercion to chars, it's still correct,
because of implicit widening coercion in JVM from C to I

 #KT-15105 Fixed
2017-02-21 12:33:45 +03:00
Denis Zharkov
378acbf7ec Minor. Clarify method patchOpcode contract 2017-02-21 12:33:45 +03:00
Alexander Udalov
21449763ab Add extension CompilerConfiguration.languageVersionSettings for convenience 2017-02-21 10:58:19 +03:00
Alexander Udalov
103bd6dbde Minor, convert CommonConfigurationKeys to Kotlin 2017-02-20 16:18:00 +03:00
Alexander Udalov
d499998655 Inject CompilerConfiguration instead of LanguageVersionSettings
LanguageVersionSettings can be read from the configuration. Also, the
configuration may be used for other stuff, not related to language version
settings, soon
2017-02-20 16:18:00 +03:00
Alexander Udalov
4b31e75550 Refactor createContainerForLazyResolve/createLazyResolveSession 2017-02-20 16:18:00 +03:00
Alexander Udalov
ee1152bc98 Simplify injection of LanguageVersionSettings into JVM analysis
Pass the LanguageVersionSettings instance inside the CompilerConfiguration,
since it's needed anyway. In compiler and tests, the configuration comes from
KotlinCoreEnvironment; in IDE, we're constructing it in JvmAnalyzerFacade
2017-02-20 16:18:00 +03:00
Denis Zharkov
f2aacf774e Get rid of redundant not-null assertion for parameter
The problem was that in `Function<T>.apply(T)` T is now not-platform,
so when checking if not-null assertion is needed for parameter in SAM,
it's defined by the upper bounds of T that is a platform (Any..Any?),
and while it's definitely not marked as nullable it's still nullable
in a sense that it can contain null as a value.

So the solution is obvious

 #KT-16413 Fixed
2017-02-20 15:46:49 +03:00
Dmitry Jemerov
1bb7a617ad Don't overwrite explicitly specified language version in facet with version from dependencies; add tests for setting language version based on dependencies
(cherry picked from commit fc2b9f6)
2017-02-20 11:32:11 +01:00
Denis Zharkov
a3baca829f Drop KotlinTarget.INNER_CLASS entry
In most of the cases it was used together with CLASS_ONLY and vice versa
They only case when CLASS_ONLY was used without INNER_CLASS
is possibleParentTargetMap.COMPANION_KEYWORD.

But after diagnostic NESTED_OBJECT_NOT_ALLOWED has been introduced,
there's no sense in the restriction of exactly the companion's parent

For clarification see test data changed
2017-02-20 13:24:42 +03:00
Denis Zharkov
d1b17f050b Prohibit objects inside inner classes
#KT-16232 Fixed
2017-02-20 13:24:42 +03:00
Denis Zharkov
5b9b003e02 Prohibit inner sealed classes
#KT-16233 Fixed
2017-02-20 13:24:42 +03:00
Alexey Andreev
86d1c7b7ec JS: fix absence of temporary variable in secondary constructors. See KT-16377 2017-02-20 11:31:38 +03:00
Alexey Tsvetkov
3b222f13f3 Replace daemon's message after start with constant string
#KT-15783 fixed

When a daemon client cannot find an existing daemon, it starts a new one.
The client waits for a daemon to start and initialize.
Then the daemon is expected to signal that it is ready for compiling by printing message in stdout.
Before this change the message was the daemons' run path (a directory where all daemons store
their "flag" files).
However the path printed by the daemon was not matched by the path expected by the client somehow
on Windows for a user with a username containing non-English letters.
This commit replaces the message with the constant string.
2017-02-18 19:35:06 +03:00
Alexey Tsvetkov
b2de822fd4 Start daemon with explicit server ip address to prevent host name resolution 2017-02-18 19:35:06 +03:00
Denis Zharkov
0d8f64353a Fix JVM signature mapping for multi-dimensional arrays
#KT-11314 Fixed
2017-02-17 17:50:43 +03:00
Dmitry Jemerov
83d64e8eba Don't replace explicitly configured project settings with autodetected ones
(cherry picked from commit f16f975)
2017-02-17 14:44:37 +01:00
Nikolay Krasko
7bae72113b Rename: ExtraSteppingFilter -> KotlinExtraSteppingFilter 2017-02-17 15:57:11 +03:00
Nikolay Krasko
f7391f6c1a Minor: refactoring 2017-02-17 15:57:11 +03:00
Nikolay Krasko
d58707972d Keep empty bodies for declarations with comments (KT-16078)
#KT-16078 Fixed
2017-02-17 15:57:11 +03:00
Denis Zharkov
e16b0524b6 Fix inline codegen on local functions inside inlined lambda
The problem was that anonymous classes wasn't regenerated
although they capture another anonymous class that is a subject
for regeneration

 #KT-8689 Fixed
2017-02-17 13:48:19 +03:00
Alexey Tsvetkov
dfb60ba4ac Minor: remove the word 'experimental' from Gradle IC description 2017-02-16 21:27:04 +03:00
Alexey Tsvetkov
62a15e803b Avoid storing absolute paths in SyncOutputTask
#KT-16003 fixed
2017-02-16 21:26:50 +03:00
Alexey Tsvetkov
6e0f3b7f1f Avoid having -d and -module set at the same time
#KT-14619 fixed
2017-02-16 21:26:50 +03:00
Alexey Tsvetkov
667c00e3ed Copy compiler arguments from compile task to kapt task
#KT-15994 fixed
2017-02-16 21:26:50 +03:00
Dmitry Jemerov
3225c93ce0 Don't pass paths to non-existing metadata files from dependent modules 2017-02-16 19:16:19 +01:00
Mikhail Glukhikh
797813a8d4 Change log update (final) for 1.1-RC 2017-02-16 18:55:14 +03:00
Dmitry Jemerov
6aa3c26f78 Disable facet detection; force detection of API/language level from dependencies on project opening 2017-02-16 16:51:09 +01:00
Dmitry Jemerov
58713270bb Ask to update runtime library when increasing language version for module 2017-02-16 16:50:47 +01:00
Alexander Udalov
de2117663c Fix overload resolution ambiguity on *Array.clone() with runtime 1.0
#KT-16371 Fixed
2017-02-16 18:46:05 +03:00
Alexander Udalov
9d11f0b92f Minor, check every deserialized value in refsAreSerializable.kt 2017-02-16 18:00:19 +03:00
Alexander Udalov
1ee2053a16 Make callable references Serializable on JVM
#KT-11254 Fixed
2017-02-16 18:00:18 +03:00
Dmitry Jemerov
4d451356eb Quickfixes to enable unsupported and experimental features handle API level correctly and support updating the runtime library 2017-02-16 12:41:42 +01:00
Dmitry Jemerov
ea228a2fa8 Fix testdata for SimpleKotlinRenderLogTest 2017-02-16 11:43:16 +01:00
Alexander Udalov
612481f0f4 Fix stub builder for builtins after cdeabf26b4 2017-02-16 10:35:07 +03:00
Alexander Udalov
cdeabf26b4 Fix NPE from KotlinBuiltInDecompiler
This happened because of bae955aafd: similarly to the corresponding code in
the compiler, the IDE should also skip the metadata for kotlin.Cloneable when
decompiling built-ins because the deserializer is not going to resolve this
class from the metadata
2017-02-16 01:31:44 +03:00
Mikhail Glukhikh
4d4e2c5c94 Change log for 1.1-RC updated
(cherry picked from commit 4897af1)
2017-02-15 20:53:44 +03:00
Alexander Udalov
8e407d548a Suggest to provide explicit dependency on new kotlin-reflect
In case when there's kotlin-stdlib 1.1 and kotlin-reflect 1.0 in the classpath
2017-02-15 20:43:25 +03:00
Alexander Udalov
71fcb07fad Infer API version from older runtime in compiler's classpath
For example, if you invoke kotlinc 1.1 with kotlin-stdlib 1.0 in the classpath,
we now infer -api-version 1.0 automatically
2017-02-15 20:43:25 +03:00
Alexander Udalov
b56639a775 Filter out files with the same paths in runtime version checker
To prevent listing them several times in the diagnostic message
2017-02-15 20:43:25 +03:00
Alexander Udalov
8457ab7c58 Report warnings instead of errors in runtime version checker 2017-02-15 20:43:25 +03:00
Alexander Udalov
ba84338862 Support smart cast for nullability in LHS of class literal
#KT-16291 Fixed
2017-02-15 20:43:25 +03:00
Alexander Udalov
bae955aafd Serialize metadata for Cloneable and discard it during deserialization
#KT-16358 Fixed
2017-02-15 20:43:25 +03:00
Alexander Udalov
46bd64f59a Rename FunctionImpl -> FunctionBase, restore abstract class FunctionImpl
This fixes the IncompatibleClassChangeError which happens when kotlin-reflect
1.0.x and kotlin-stdlib 1.1.x are in the classpath

 #KT-16358 In Progress
2017-02-15 20:43:25 +03:00
Dmitry Jemerov
41f7950ab8 UAST tests: don't null out the application if we have a valid one that we restored from a previous test 2017-02-15 18:21:37 +01:00
Anton Bannykh
4c808e8691 JS: concat vararg arguments using Kotlin.concat and Kotlin.concatPrimitive functions in order to be binary compatible with (Kotlin PrimitiveArray -> JS TypedArrays) mapping. 2017-02-15 18:58:29 +03:00
Ilya Gorbunov
a903c4ab0e Change log clarifications regarding stdlib
(cherry picked from commit ba857a83ff)
2017-02-15 18:17:11 +03:00
Dmitry Jemerov
7704310359 Fix Kotlin facet autodetection so that it actually works and stores the correct language/API level based on project dependencies 2017-02-15 15:48:43 +01:00
Mikhail Glukhikh
3bc322c2ce Change log for 1.1-RC updated 2017-02-15 17:45:47 +03:00
Dmitry Jemerov
f06d46fe9a Advance until-build to 172.* 2017-02-15 14:43:53 +01:00
Yan Zhulanow
8e9536f61d Revert "Kapt3: Add generated source files to Java compile task after kapt execution. Filter only .java files."
This reverts commit 82c2ce3a33.
2017-02-15 16:28:33 +03:00
Yan Zhulanow
35b41b9401 Kapt3: Fix annotation processor option passing 2017-02-15 16:28:26 +03:00
Dmitry Jemerov
95bfe8668d UAST tests no longer leave a disposed application around 2017-02-15 12:56:21 +01:00
Alexey Sedunov
5d65e6bc9b Kotlin Facet: Facet migration workaround for the case pre-1.1-beta -> 1.1.rc+ (reset useProjectSettings to false for old configurations) 2017-02-15 14:40:09 +03:00
Alexey Sedunov
2e01f62afe Kotlin Facet: Detect language/API version by stdlib when "Use project settings" is enabled, but project-level language/api version is not specified explicitly 2017-02-15 14:40:04 +03:00
Alexey Sedunov
0d2122bb1d Kotlin Facet: Do not rewrite language/API version based on compiler arguments if they do not contain explicit language/API version 2017-02-15 14:30:41 +03:00
Alexey Sedunov
2790fcf4bd Kotlin Facet: Synchronize version info on opening the configuration editor 2017-02-15 14:30:40 +03:00
Dmitry Jemerov
060a865fb1 Use correct resolution facade for resolving cross-module links in KDoc comments
#KT-15647 Fixed
2017-02-15 12:08:18 +01:00
Mikhail Glukhikh
4b7380bea4 Change log for 1.1-RC added 2017-02-15 12:49:22 +03:00
Alexander Udalov
8e3cb912c7 Make Ref classes for shared vars Serializable
#KT-14566 Fixed
2017-02-15 10:46:48 +03:00
Alexander Udalov
c10524586a Use proguard to remove unused symbols from kotlin-reflect.jar
#KT-16268 Fixed
2017-02-15 10:46:48 +03:00
Alexander Udalov
2e8bfde2e7 Move -Xskip-metadata-version-check from JVM to common arguments
To be used in JS
2017-02-15 10:46:48 +03:00
Alexander Udalov
a1a71a01b1 Drop JvmMetadataVersion.skipCheck, support this correctly
Pass the value of this flag via DeserializationConfiguration
2017-02-15 10:46:48 +03:00
Alexey Sedunov
e1463f9e0f Kotlin Facet: Fix detection of pre-1.1-beta JS-stdlib dependencies 2017-02-14 18:28:44 +03:00
Mikhail Zarechenskiy
5515a63911 Replace KotlinBuiltIns.isBuiltIn with corresponding package checking
Method `isBuiltIn` may not work correctly as built-ins are becoming
more and more like a usual dependency. Also behaviour of this method is
depend on the target platform.
2017-02-14 16:21:17 +03:00
Alexey Sedunov
8c84717cbc Kotlin Facet: Reset all coroutine support flags before importing them frm Gradle 2017-02-14 16:19:21 +03:00
Vyacheslav Gerasimov
a2e429a912 Fixed exception in getUastLocation of class annotation argument
#KT-16326 Fixed
2017-02-14 15:56:37 +03:00
Stanislav Erokhin
b6fa10cf9e Disable some features when LV=1.1 API=1.0.
Feature list:
 - bound callable references
 - local delegated properties
 - coroutines.

#KT-16017 Fixed
2017-02-13 20:29:38 +03:00
Dmitry Jemerov
be0211cd49 Ugly deadlock workaround for KT-16149: members of DataBindingComponent are calculated via annotations search which causes resolve reentrering 2017-02-13 17:20:10 +01:00
Simon Ogorodnik
2490318f93 KT-16076 Completion inserts FQN kotlin.text.String
KT-14831 Don't add import statement and FQN on converting lambda to reference if typealias is used
KT-16088 Completion wrongly inserts FQN for `kotlin` package
 #KT-16076 fixed
 #KT-14831 fixed
 #KT-16088 fixed
2017-02-13 16:48:14 +03:00
Ilya Gorbunov
fee676a281 Introduce 'takeUnless' function which is like 'takeIf' but with the predicate inverted.
#KT-7858
2017-02-13 16:07:34 +03:00
Sergey Igushkin
9e1afe71f2 Fixed Kotlin2Js output not being the output of the compileKotlin2Js tasks.
Therefore, fixed Kotlin2Js output not present in JAR.
Reworked the clean behavior in regard to compileKotlin2Js tasks.
Fixed duplicate source roots passed to the compiler.

Issues:
- #KT-15829 Fixed
- #KT-16267 Fixed
- #KT-15902 Fixed
2017-02-13 15:44:05 +03:00
Anton Bannykh
ad313750e7 JS: Fixed lateinit property initialization 2017-02-13 14:56:50 +03:00
Alexey Sedunov
1452d7e4a6 Kotlin Gradle Plugin: Extend implicit argument set 2017-02-13 14:53:18 +03:00
Alexey Sedunov
75c56d58ae Line Markers: Do not attempt to resolve suspend call candidates which are not call-like expressions 2017-02-13 14:53:17 +03:00
Alexey Sedunov
add16dec3d Extract Function: Fix detection of suspend calls containing extracted parameters
#KT-16251 Fixed
2017-02-13 14:53:17 +03:00
Alexey Sedunov
574a0e629e Kotlin Facet: Fix stdlib dependency detection 2017-02-13 14:53:16 +03:00
Alexey Sedunov
7fbca4e122 Kotlin Facet: Scan classpath backwards when looking for kotlin-gradle-plugin dependency
#KT-15899 Fixed
2017-02-13 14:53:15 +03:00
Alexey Sedunov
330beebb2c Kotlin Facet: Check contradictory values of "coroutine support" option
#KT-16109 Fixed
2017-02-13 14:53:14 +03:00
Alexander Udalov
9397b16bb9 Minor, fix typo in comment 2017-02-13 14:10:19 +03:00
Alexander Udalov
407815449a Minor, improve error message 2017-02-13 14:09:58 +03:00
Alexander Udalov
57f2feb6fb Fix unreported deprecation on variables called as functions
#KT-16272 Fixed
2017-02-13 14:09:53 +03:00
Alexander Udalov
6793861fd4 Add target FIELD for SinceKotlin, annotate CallableReference.receiver/NO_RECEIVER 2017-02-13 14:09:43 +03:00
Alexander Udalov
20d856fa77 Minor, remove blank line in extra help 2017-02-13 14:09:38 +03:00
Alexander Udalov
8fee62a8c5 Minor, explain what CompilerMessageSeverity.STRONG_WARNING is 2017-02-13 12:11:16 +03:00
Alexander Udalov
4c9afb9d20 Move testable IS_PRE_RELEASE flag to KotlinCompilerVersion
It'll be used in the JS back-end as well soon, so
DeserializedDescriptorResolver is not the best place for it
2017-02-13 12:11:15 +03:00
Stanislav Erokhin
3efda0e45a Reserve yield if it isn't function call. 2017-02-13 02:53:37 +03:00
Ilya Chernikov
9eae929084 Fixes after review 2017-02-11 16:27:27 +01:00
Ilya Chernikov
39d204c550 Adjust test after introducing shutdown delay 2017-02-11 16:27:26 +01:00
Ilya Chernikov
cb7de0e262 Implement more reliable daemon election, fixes KT-15562
also making shutdown more reliable
2017-02-11 16:27:25 +01:00
Ilya Chernikov
ebf9e386b0 Add test reproducing "Service is dying" problem (KT-15562) 2017-02-11 16:27:24 +01:00
Alexey Andreev
7192529733 JS: drop support of old library format 2017-02-10 21:04:50 +03:00
Ilya Chernikov
82320bdf7d Make maven/aether dependencies optional in the script-util
(cherry picked from commit 8197240)
2017-02-10 16:03:06 +01:00
Ilya Chernikov
46894da981 Get rid of daemon-client dependency on openapi, making others "provided"
(cherry picked from commit 175d74c)
2017-02-10 16:02:55 +01:00
Ilya Chernikov
f6fd9441e9 Move scripting options into separate panel
(cherry picked from commit c06592e)
2017-02-10 14:44:36 +01:00
Dmitry Petrov
20dc1a047d KT-16250 Handle type alias as imported name qualifier
#KT-16250 Fixed
2017-02-10 16:32:07 +03:00
Denis Zharkov
5f843f6759 Fix intrinsic for String.plus for explicit calls
#KT-14567 Fixed
2017-02-10 16:05:15 +03:00
Denis Zharkov
fcb4db0226 Remove redundant ACC_VARARGS on methods generated with @JvmOverloads
#KT-15424 Fixed
2017-02-10 16:05:15 +03:00
Denis Zharkov
1f179a6f01 Add test on obsolete issue
#KT-15196 Obsolete
2017-02-10 16:05:15 +03:00
Denis Zharkov
b989bfce59 Fix VerifyError with @JvmStatic annotated getter
The problem was that for property getter 'context.getContextDescriptor()'
references the containing property, while 'context.getFunctionDescriptor()'
the accessor itself

 #KT-15594 Fixed
2017-02-10 16:05:15 +03:00
Denis Zharkov
dd275eda78 Minor. Refine class name: JvmStaticGenerator -> JvmStaticInCompanionObjectGenerator 2017-02-10 16:05:15 +03:00
Dmitry Jemerov
87187437ab Update UAST to version 1.0.11 2017-02-10 13:55:25 +01:00
Ilya Chernikov
da2f310895 Convert line endings when creating ReplCodeLine, fixes KT-15861
(cherry picked from commit 894ee4c)
2017-02-09 22:00:30 +01:00
6589 changed files with 65576 additions and 70357 deletions

2
.idea/ant.xml generated
View File

@@ -3,7 +3,7 @@
<component name="AntConfiguration">
<buildFile url="file://$PROJECT_DIR$/compiler/frontend/buildLexer.xml" />
<buildFile url="file://$PROJECT_DIR$/build.xml">
<antCommandLine value="-J-XX:MaxPermSize=100m -J-ea" />
<antCommandLine value="-J-ea" />
<maximumHeapSize value="1024" />
</buildFile>
<buildFile url="file://$PROJECT_DIR$/update_dependencies.xml" />

View File

@@ -11,7 +11,6 @@
<element id="directory" name="META-INF">
<element id="dir-copy" path="$PROJECT_DIR$/jps-plugin/src/META-INF" />
</element>
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/cli-parser-1.1.2.jar" path-in-jar="/" />
<element id="module-output" name="cli-common" />
<element id="module-output" name="idea-jps-common" />
<element id="module-output" name="jps-plugin" />

7
.idea/dictionaries/4u7.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="4u7">
<words>
<w>foldable</w>
</words>
</dictionary>
</component>

View File

@@ -1,7 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false">
<profile version="1.0">
<option name="myName" value="idea.default" />
<option name="myLocal" value="false" />
<inspection_tool class="AbstractMethodCallInConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ArchaicSystemPropertyAccess" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AssignmentToForLoopParameter" enabled="true" level="WARNING" enabled_by_default="true">
@@ -236,10 +235,6 @@
<scope name="idea openapi" level="WARNING" enabled="true" />
<scope name="runtime.classes" level="ERROR" enabled="true" />
</inspection_tool>
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
</inspection_tool>
<inspection_tool class="LoopToCallChain" enabled="false" level="INFO" enabled_by_default="false" />
<inspection_tool class="MethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_onlyPrivateOrFinal" value="false" />
@@ -347,11 +342,12 @@
<constraint name="__context__" script="&quot;&quot;" within="" contains="" />
</searchConfiguration>
</inspection_tool>
<inspection_tool class="SameParameterValue" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="SetReplaceableByEnumSet" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SetupCallsSuperSetup" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SetupIsPublicVoidNoArg" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SimplifiableIfStatement" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="Since15" enabled="true" level="ERROR" enabled_by_default="true">
<inspection_tool class="Since15" enabled="false" level="ERROR" enabled_by_default="false">
<scope name="IDEA Test Sources" level="ERROR" enabled="false" />
</inspection_tool>
<inspection_tool class="SocketResource" enabled="true" level="WARNING" enabled_by_default="true">

4
.idea/kotlinc.xml generated
View File

@@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinCommonCompilerArguments">
<option name="languageVersion" value="1.1" />
<option name="apiVersion" value="1.1" />
</component>
<component name="KotlinCompilerSettings">
<option name="additionalArguments" value="-version -Xallow-kotlin-package -Xskip-metadata-version-check" />
</component>

View File

@@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="cli-parser">
<CLASSES>
<root url="jar://$PROJECT_DIR$/dependencies/cli-parser-1.1.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/cli-parser-1.1.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -4,11 +4,11 @@
<root url="file://$PROJECT_DIR$/annotations" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/guava-17.0.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/guava-19.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/guava-17.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/guava-19.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -9,7 +9,7 @@
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/guava-17.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/guava-19.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/asm5-src.zip!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
</SOURCES>

View File

@@ -9,7 +9,7 @@
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/guava-17.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/guava-19.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/asm5-src.zip!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
</SOURCES>

View File

@@ -10,7 +10,7 @@
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/asm5-src.zip!/" />
<root url="jar://$PROJECT_DIR$/dependencies/guava-17.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/guava-19.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
</SOURCES>
</library>

View File

@@ -5,6 +5,7 @@
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/properties/lib/properties.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/properties/lib/resources_en.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>

3
.idea/misc.xml generated
View File

@@ -6,7 +6,6 @@
</properties>
</component>
<component name="EntryPointsManager">
<entry_points version="2.0" />
<list size="1">
<item index="0" class="java.lang.String" itemvalue="javax.inject.Inject" />
</list>
@@ -49,7 +48,7 @@
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="SuppressABINotification">

1
.idea/modules.xml generated
View File

@@ -92,6 +92,7 @@
<module fileurl="file://$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-ide/sam-with-receiver-ide.iml" filepath="$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-ide/sam-with-receiver-ide.iml" />
<module fileurl="file://$PROJECT_DIR$/core/script.runtime/script.runtime.iml" filepath="$PROJECT_DIR$/core/script.runtime/script.runtime.iml" group="core" />
<module fileurl="file://$PROJECT_DIR$/compiler/serialization/serialization.iml" filepath="$PROJECT_DIR$/compiler/serialization/serialization.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/plugins/source-sections/source-sections-compiler/source-sections-compiler.iml" filepath="$PROJECT_DIR$/plugins/source-sections/source-sections-compiler/source-sections-compiler.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/compiler/tests-common/tests-common.iml" filepath="$PROJECT_DIR$/compiler/tests-common/tests-common.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/tests-ir-jvm/tests-ir-jvm.iml" filepath="$PROJECT_DIR$/compiler/tests-ir-jvm/tests-ir-jvm.iml" group="compiler/ir" />
<module fileurl="file://$PROJECT_DIR$/plugins/uast-kotlin/uast-kotlin.iml" filepath="$PROJECT_DIR$/plugins/uast-kotlin/uast-kotlin.iml" group="plugins/lint" />

View File

@@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx900m -XX:MaxPermSize=320m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=64m -Djna.nosys=true" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=64m -Djna.nosys=true" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />

View File

@@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1100m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx900m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />

View File

@@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx700m -XX:MaxPermSize=300m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=64m -Djna.nosys=true" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=64m -Djna.nosys=true" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />

View File

@@ -3,6 +3,165 @@
<!-- Find: ([^\`/\[])(KT-\d+) -->
<!-- Replace: $1[`$2`](https://youtrack.jetbrains.com/issue/$2) -->
## 1.1.1
### IDE
- [`KT-16714`](https://youtrack.jetbrains.com/issue/KT-16714) J2K: Write access is allowed from event dispatch thread only
### Compiler
- [`KT-16801`](https://youtrack.jetbrains.com/issue/KT-16801) Accessors of `@PublishedApi` property gets mangled
- [`KT-16673`](https://youtrack.jetbrains.com/issue/KT-16673) Potentially problematic code causes exception when work with SAM adapters
### Libraries
- [`KT-16557`](https://youtrack.jetbrains.com/issue/KT-16557) Correct `SinceKotlin(1.1)` for all declarations in `kotlin.reflect.full`
## 1.1.1-RC
### IDE
- [`KT-16481`](https://youtrack.jetbrains.com/issue/KT-16481) Kotlin debugger & bytecode fail on select statement blocks (IllegalStateException: More than one package fragment)
### Gradle support
- [`KT-15783`](https://youtrack.jetbrains.com/issue/KT-15783) Gradle builds don't use incremental compilation due to an error: "Could not connect to kotlin daemon"
- [`KT-16434`](https://youtrack.jetbrains.com/issue/KT-16434) Gradle plugin does not compile androidTest sources when Jack is enabled
- [`KT-16546`](https://youtrack.jetbrains.com/issue/KT-16546) Enable incremental compilation in gradle by default
### Compiler
- [`KT-16184`](https://youtrack.jetbrains.com/issue/KT-16184) AbstractMethodError in Kapt3ComponentRegistrar while compiling from IntelliJ using Kotlin 1.1.0
- [`KT-16578`](https://youtrack.jetbrains.com/issue/KT-16578) Fix substitutor for synthetic SAM adapters
- [`KT-16581`](https://youtrack.jetbrains.com/issue/KT-16581) VerifyError when calling default value parameter with jvm-target 1.8
- [`KT-16583`](https://youtrack.jetbrains.com/issue/KT-16583) Cannot access private file-level variables inside a class init within the same file if a secondary constructor is present
- [`KT-16587`](https://youtrack.jetbrains.com/issue/KT-16587) AbstractMethodError: Delegates not generated correctly for private interfaces
- [`KT-16598`](https://youtrack.jetbrains.com/issue/KT-16598) Incorrect error: The feature "bound callable references" is only available since language version 1.1
- [`KT-16621`](https://youtrack.jetbrains.com/issue/KT-16621) Kotlin compiler doesn't report an error if a class implements Annotation interface but doesn't implement annotationType method
- [`KT-16441`](https://youtrack.jetbrains.com/issue/KT-16441) `NoSuchFieldError: $$delegatedProperties` when delegating through `provideDelegate` in companion object
### JavaScript support
- Prohibit function types with receiver as parameter types of external declarations
- Remove extension receiver for function parameters in `jQuery` declarations
## 1.1
### Compiler exceptions
- [`KT-16411`](https://youtrack.jetbrains.com/issue/KT-16411) Exception from compiler when try to inline callable reference to class constructor inside object
- [`KT-16412`](https://youtrack.jetbrains.com/issue/KT-16412) Exception from compiler when try call SAM constructor where argument is callable reference to nested class inside object
- [`KT-16413`](https://youtrack.jetbrains.com/issue/KT-16413) When we create sam adapter for java.util.function.Function we add incorrect null-check for argument
### Standard library
- [`KT-6561`](https://youtrack.jetbrains.com/issue/KT-6561) Drop java.util.Collections package from js stdlib
- `javaClass` extension property is no more deprecated due to migration problems
### IDE
- [`KT-16329`](https://youtrack.jetbrains.com/issue/KT-16329) Inspection "Calls to staic methods in Java interfaces..." always reports warning undependent of jvm-target
## 1.1-RC
### Reflection
- [`KT-16358`](https://youtrack.jetbrains.com/issue/KT-16358) Incompatibility between kotlin-reflect 1.0 and kotlin-stdlib 1.1 fixed
### Compiler
#### Coroutine support
- [`KT-15938`](https://youtrack.jetbrains.com/issue/KT-15938) Changed error message for calling suspend function outside of suspendable context
- [`KT-16092`](https://youtrack.jetbrains.com/issue/KT-16092) Backend crash fixed: "Don't know how to generate outer expression" for destructuring suspend lambda
- [`KT-16093`](https://youtrack.jetbrains.com/issue/KT-16093) Annotations are retained during reading the binary representation of suspend functions
- [`KT-16122`](https://youtrack.jetbrains.com/issue/KT-16122) java.lang.VerifyError fixed in couroutines: (String, null, suspend () -> String)
- [`KT-16124`](https://youtrack.jetbrains.com/issue/KT-16124) Marked as UNSUPPORTED: suspension points in default parameters
- [`KT-16219`](https://youtrack.jetbrains.com/issue/KT-16219) Marked as UNSUPPORTED: suspend get/set, in/!in operators for
- [`KT-16145`](https://youtrack.jetbrains.com/issue/KT-16145) Beta-2 coroutine regression fixed (wrong code generation)
#### Kapt3
- [`KT-15524`](https://youtrack.jetbrains.com/issue/KT-15524) Fix javac error reporting in Kotlin daemon
- [`KT-15721`](https://youtrack.jetbrains.com/issue/KT-15721) JetBrains nullability annotations are now returned from Element.getAnnotationMirrors()
- [`KT-16146`](https://youtrack.jetbrains.com/issue/KT-16146) Fixed work in verbose mode
- [`KT-16153`](https://youtrack.jetbrains.com/issue/KT-16153) Ignore declarations with illegal Java identifiers
- [`KT-16167`](https://youtrack.jetbrains.com/issue/KT-16167) Fixed compilation error with kapt arguments in build.gradle
- [`KT-16170`](https://youtrack.jetbrains.com/issue/KT-16170) Stub generator now adds imports for corrected error types to stubs
- [`KT-16176`](https://youtrack.jetbrains.com/issue/KT-16176) javac's finalCompiler log is now used to determine annotation processing errors
#### Backward compatibility
- [`KT-16017`](https://youtrack.jetbrains.com/issue/KT-16017) More graceful error message for disabled features
- [`KT-16073`](https://youtrack.jetbrains.com/issue/KT-16073) Improved backward compatibility mode with version 1.0 on JDK dependent built-ins
- [`KT-16094`](https://youtrack.jetbrains.com/issue/KT-16094) Compiler considers API availability when compiling language features requiring runtime support
- [`KT-16171`](https://youtrack.jetbrains.com/issue/KT-16171) Fixed regression "Unexpected container error on Kotlin 1.0 project"
- [`KT-16199`](https://youtrack.jetbrains.com/issue/KT-16199) Do not import "kotlin.comparisons.*" by default in language version 1.0 mode
#### Various issues
- [`KT-16225`](https://youtrack.jetbrains.com/issue/KT-16225) enumValues non-reified stub implementation references nonexistent method no more
- [`KT-16291`](https://youtrack.jetbrains.com/issue/KT-16291) Smart cast works now when getting class of instance
- [`KT-16380`](https://youtrack.jetbrains.com/issue/KT-16380) Show warning when running the compiler under Java 6 or 7
### JavaScript backend
- [`KT-16144`](https://youtrack.jetbrains.com/issue/KT-16144) Fixed inlining of functions called through inheritor ("fake" override) from another module
- [`KT-16158`](https://youtrack.jetbrains.com/issue/KT-16158) Error is not reported now when library path contains JAR file without JS metadata, report warning instead
- [`KT-16160`](https://youtrack.jetbrains.com/issue/KT-16160) Companion object dispatch receiver translation fixed
### Standard library
- [`KT-7858`](https://youtrack.jetbrains.com/issue/KT-7858) Add extension function `takeUnless`
- `javaClass` extension property is deprecated, use `instance::class.java` instead
- Massive deprecations are coming in JS standard library in `kotlin.dom` and `kotlin.dom.build` packages
### IDE
#### Configuration issues
- [`KT-15899`](https://youtrack.jetbrains.com/issue/KT-15899) Kotlin facet: language and api version for submodule setup for 1.0 are filled now as 1.0 too
- [`KT-15914`](https://youtrack.jetbrains.com/issue/KT-15914) Kotlin facet works now with multi-selected modules in Project Settings too
- [`KT-15954`](https://youtrack.jetbrains.com/issue/KT-15954) Does not suggest to configure kotlin for the module after each new kt-file creation
- [`KT-16157`](https://youtrack.jetbrains.com/issue/KT-16157) freeCompilerArgs are now imported from Gradle into IDEA
- [`KT-16206`](https://youtrack.jetbrains.com/issue/KT-16206) Idea no more refuses to compile a kotlin project defined as a maven project
- [`KT-16312`](https://youtrack.jetbrains.com/issue/KT-16312) Kotlin facet: import from gradle: don't import options which are set implicitly already
- [`KT-16325`](https://youtrack.jetbrains.com/issue/KT-16325) Kotlin facet: correct configuration after upgrading the IDE plugin
- [`KT-16345`](https://youtrack.jetbrains.com/issue/KT-16345) Kotlin facet: detect JavaScript if the module has language 1.0 `kotlin-js-library` dependency
#### Coroutine support
- [`KT-16109`](https://youtrack.jetbrains.com/issue/KT-16109) Error fixed: The -Xcoroutines can only have one value
- [`KT-16251`](https://youtrack.jetbrains.com/issue/KT-16251) Fix detection of suspend calls containing extracted parameters
#### Intention actions, inspections and quick-fixes
##### 2017.1 compatibility
- [`KT-15870`](https://youtrack.jetbrains.com/issue/KT-15870) "Package name does not match containing directory" inspection: fixed throwable "AWT events are not allowed inside write action"
- [`KT-15924`](https://youtrack.jetbrains.com/issue/KT-15924) Create Test action: fixed throwable "AWT events are not allowed inside write action"
##### Bug fixes
- [`KT-14831`](https://youtrack.jetbrains.com/issue/KT-14831) Import statement and FQN are not added on converting lambda to reference for typealias
- [`KT-15545`](https://youtrack.jetbrains.com/issue/KT-15545) Inspection "join with assignment" does not change now execution order for properties
- [`KT-15744`](https://youtrack.jetbrains.com/issue/KT-15744) Fix: intention to import `sleep` wrongly suggests `Thread.sleep`
- [`KT-16000`](https://youtrack.jetbrains.com/issue/KT-16000) Inspection "join with assignment" handles initialization with 'this' correctly
- [`KT-16009`](https://youtrack.jetbrains.com/issue/KT-16009) Auto-import for JDK classes in .kts files
- [`KT-16104`](https://youtrack.jetbrains.com/issue/KT-16104) Don't insert modifiers (e.g. suspend) before visibility
#### Completion
- [`KT-16076`](https://youtrack.jetbrains.com/issue/KT-16076) Completion does not insert more FQN kotlin.text.String
- [`KT-16088`](https://youtrack.jetbrains.com/issue/KT-16088) Completion does not insert more FQN for `kotlin` package
- [`KT-16110`](https://youtrack.jetbrains.com/issue/KT-16110) Keyword 'suspend' completion inside generic arguments
- [`KT-16243`](https://youtrack.jetbrains.com/issue/KT-16243) Performance enhanced after variable of type `ArrayList`
#### Various issues
- [`KT-15291`](https://youtrack.jetbrains.com/issue/KT-15291) 'Find usages' now does not report property access as usage of getter method in Java class with parameter
- [`KT-15647`](https://youtrack.jetbrains.com/issue/KT-15647) Exception fixed: KDoc link to member of class from different package and module
- [`KT-16071`](https://youtrack.jetbrains.com/issue/KT-16071) IDEA deadlock fixed: when typing "parse()" in .kt file
- [`KT-16149`](https://youtrack.jetbrains.com/issue/KT-16149) Intellij Idea 2017.1/Android Studio 2.3 beta3 and Kotlin plugin 1.1-beta2 deadlock fixed
### Coroutine libraries
- [`KT-15716`](https://youtrack.jetbrains.com/issue/KT-15716) Introduced startCoroutineUninterceptedOrReturn coroutine intrinsic
- [`KT-15718`](https://youtrack.jetbrains.com/issue/KT-15718) createCoroutine now returns safe continuation
- [`KT-16155`](https://youtrack.jetbrains.com/issue/KT-16155) Introduced createCoroutineUnchecked intrinsic
### Gradle support
- [`KT-15829`](https://youtrack.jetbrains.com/issue/KT-15829) Gradle Kotlin JS plugin: removed false "Duplicate source root:" warning for kotlin files
- [`KT-15902`](https://youtrack.jetbrains.com/issue/KT-15902) JS: gradle task output is now considered as source set output
- [`KT-16174`](https://youtrack.jetbrains.com/issue/KT-16174) Error fixed during IDEA-Gradle synchronization for Kotlin JS
- [`KT-16267`](https://youtrack.jetbrains.com/issue/KT-16267) JS: fixed regression in 1.1-beta2 for multi-module gradle project
- [`KT-16274`](https://youtrack.jetbrains.com/issue/KT-16274) Kotlin JS Gradle unexpected compiler error / absolute path to output file
- [`KT-16322`](https://youtrack.jetbrains.com/issue/KT-16322) Circlet project Gradle import issue fixed
### REPL
- [`KT-15861`](https://youtrack.jetbrains.com/issue/KT-15861) Use windows line separator in kotlin's JSR implementation
- [`KT-16126`](https://youtrack.jetbrains.com/issue/KT-16126) Proper `jvmTarget` for REPL compilation
## 1.1-Beta2
### Language related changes

View File

@@ -29,8 +29,8 @@ internal object KotlinAntTaskUtil {
private val libPath: File by lazy {
// Find path of kotlin-ant.jar in the filesystem and find kotlin-compiler.jar in the same directory
val resourcePath = "/" + javaClass.name.replace('.', '/') + ".class"
val jarConnection = javaClass.getResource(resourcePath).openConnection() as? JarURLConnection
val resourcePath = "/" + this::class.java.name.replace('.', '/') + ".class"
val jarConnection = this::class.java.getResource(resourcePath).openConnection() as? JarURLConnection
?: throw UnsupportedOperationException("Kotlin compiler Ant task should be loaded from the JAR file")
val antTaskJarPath = File(jarConnection.jarFileURL.toURI())
@@ -54,7 +54,7 @@ internal object KotlinAntTaskUtil {
val cached = classLoaderRef.get()
if (cached != null) return cached
val myLoader = javaClass.classLoader
val myLoader = this::class.java.classLoader
if (myLoader !is AntClassLoader) return myLoader
val classLoader = ClassPreloadingUtils.preloadClasses(listOf(compilerJar), Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE, myLoader, null)

View File

@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
import org.jetbrains.kotlin.build.deserializeFromPlainText
import org.jetbrains.kotlin.build.serializeToPlainText
/**
* If you want to add a new field, check its type is supported by [serializeToPlainText], [deserializeFromPlainText]
@@ -62,7 +59,7 @@ data class JvmBuildMetaInfo(
}
fun JvmBuildMetaInfo(args: CommonCompilerArguments): JvmBuildMetaInfo =
JvmBuildMetaInfo(isEAP = DeserializedDescriptorResolver.IS_PRE_RELEASE,
JvmBuildMetaInfo(isEAP = KotlinCompilerVersion.isPreRelease(),
compilerBuildVersion = KotlinCompilerVersion.VERSION,
languageVersionString = args.languageVersion ?: LanguageVersion.LATEST.versionString,
apiVersionString = args.apiVersion ?: ApiVersion.LATEST.versionString,
@@ -75,4 +72,4 @@ fun JvmBuildMetaInfo(args: CommonCompilerArguments): JvmBuildMetaInfo =
metadataVersionPatch = JvmMetadataVersion.INSTANCE.patch,
bytecodeVersionMajor = JvmBytecodeBinaryVersion.INSTANCE.major,
bytecodeVersionMinor = JvmBytecodeBinaryVersion.INSTANCE.minor,
bytecodeVersionPatch = JvmBytecodeBinaryVersion.INSTANCE.patch)
bytecodeVersionPatch = JvmBytecodeBinaryVersion.INSTANCE.patch)

View File

@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.compilerRunner;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ComparatorUtil;
import com.sampullara.cli.Argument;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.kotlin.cli.common.parser.com.sampullara.cli.Argument;
import java.lang.reflect.Field;
import java.util.ArrayList;

View File

@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.deserialization.supertypes
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import org.jetbrains.org.objectweb.asm.*
import java.io.File
import java.security.MessageDigest
@@ -272,7 +271,7 @@ open class IncrementalCacheImpl<Target>(
ProtoBuf.Class::getPropertyList
) + classData.classProto.enumEntryList.map { classData.nameResolver.getString(it.name) }
val companionObjectChanged = createChangeInfo(classFqName.parent(), classFqName.shortName().asString().singletonOrEmptyList())
val companionObjectChanged = createChangeInfo(classFqName.parent(), listOfNotNull(classFqName.shortName().asString()))
val companionObjectMembersChanged = createChangeInfo(classFqName, memberNames)
listOf(companionObjectMembersChanged, companionObjectChanged)
@@ -780,7 +779,7 @@ sealed class ChangeInfo(val fqName: FqName) {
protected open fun toStringProperties(): String = "fqName = $fqName"
override fun toString(): String {
return this.javaClass.simpleName + "(${toStringProperties()})"
return this::class.java.simpleName + "(${toStringProperties()})"
}
}

View File

@@ -50,5 +50,5 @@ class LocalFileKotlinClass private constructor(
override fun hashCode(): Int = file.hashCode()
override fun equals(other: Any?): Boolean = other is LocalFileKotlinClass && file == other.file
override fun toString(): String = "$javaClass: $file"
override fun toString(): String = "${this::class.java}: $file"
}

View File

@@ -42,7 +42,7 @@ import java.util.*
fun Iterable<File>.javaSourceRoots(roots: Iterable<File>): Iterable<File> =
filter { it.isJavaFile() }
filter(File::isJavaFile)
.map { findSrcDirRoot(it, roots) }
.filterNotNull()
@@ -145,7 +145,7 @@ fun LookupStorage.update(
filesToCompile: Iterable<File>,
removedFiles: Iterable<File>
) {
if (lookupTracker !is LookupTrackerImpl) throw AssertionError("Lookup tracker is expected to be LookupTrackerImpl, got ${lookupTracker.javaClass}")
if (lookupTracker !is LookupTrackerImpl) throw AssertionError("Lookup tracker is expected to be LookupTrackerImpl, got ${lookupTracker::class.java}")
removeLookupsFrom(filesToCompile.asSequence() + removedFiles.asSequence())

View File

@@ -46,7 +46,7 @@ abstract class BasicMap<K : Comparable<K>, V>(
fun dump(): String {
return with(StringBuilder()) {
with(Printer(this)) {
println(this@BasicMap.javaClass.simpleName)
println(this@BasicMap::class.java.simpleName)
pushIndent()
for (key in storage.keys.sorted()) {

View File

@@ -131,7 +131,7 @@ object ConstantsMapExternalizer : DataExternalizer<Map<String, Any>> {
output.writeByte(Kind.STRING.ordinal)
IOUtil.writeString(value, output)
}
else -> throw IllegalStateException("Unexpected constant class: ${value.javaClass}")
else -> throw IllegalStateException("Unexpected constant class: ${value::class.java}")
}
}
}

View File

@@ -144,7 +144,7 @@ private fun classFileToString(classFile: File): String {
out.write("\n------ string table types proto -----\n${DebugJvmProtoBuf.StringTableTypes.parseDelimitedFrom(input)}")
if (!classHeader!!.metadataVersion.isCompatible()) {
if (!classHeader.metadataVersion.isCompatible()) {
error("Incompatible class ($classHeader): $classFile")
}

View File

@@ -81,8 +81,8 @@ fun getModificationsToPerform(
val rules = mapOf<String, (String, File) -> Modification>(
newSuffix to { path, file -> ModifyContent(path, file) },
touchSuffix to { path, file -> TouchFile(path, touchPolicy) },
deleteSuffix to { path, file -> DeleteFile(path) }
touchSuffix to { path, _ -> TouchFile(path, touchPolicy) },
deleteSuffix to { path, _ -> DeleteFile(path) }
)
val modifications = ArrayList<Modification>()
@@ -130,7 +130,7 @@ fun getModificationsToPerform(
abstract class Modification(val path: String) {
abstract fun perform(workDir: File, mapping: MutableMap<File, File>)
override fun toString(): String = "${javaClass.simpleName} $path"
override fun toString(): String = "${this::class.java.simpleName} $path"
}
class ModifyContent(path: String, val dataFile: File) : Modification(path) {

114
build.xml
View File

@@ -1,4 +1,4 @@
<project name="Kotlin" default="dist" xmlns:if="ant:if" xmlns:unless="ant:unless">
<project xmlns:if="ant:if" xmlns:unless="ant:unless" name="Kotlin" default="dist">
<import file="common.xml" optional="false"/>
<property file="resources/kotlinManifest.properties"/>
@@ -28,7 +28,8 @@
<property name="protobuf-lite.jar" value="${basedir}/dependencies/protobuf-2.6.1-lite.jar"/>
<property name="javax.inject.jar" value="${basedir}/lib/javax.inject.jar"/>
<property name="java.target" value="1.6"/>
<property name="java.target" value="1.8"/>
<property name="java.target.1.6" value="1.6"/>
<condition property="bootstrap.or.local.build" value="true">
<or>
@@ -72,7 +73,6 @@
<fileset dir="${basedir}/lib" includes="**/*.jar"/>
<fileset dir="${dependencies}" includes="jansi.jar"/>
<fileset dir="${dependencies}" includes="jline.jar"/>
<fileset dir="${dependencies}" includes="cli-parser-1.1.2.jar"/>
<fileset dir="${basedir}/ideaSDK/jps" includes="jps-model.jar"/>
</path>
@@ -406,9 +406,12 @@
byline="true" encoding="UTF-8" />
</target>
<target name="js-stdlib">
<property environment="env"/>
<target name="js-stdlib-preprocess">
<kotlin-pp src="libraries/stdlib/src" output="${intermediate-sources}/stdlib/js" profile="JS" />
</target>
<target name="js-stdlib" depends="js-stdlib-preprocess">
<property environment="env"/>
<cleandir dir="${js.stdlib.output.dir}"/>
<!-- We don't want descriptors for built-ins to be serialized, so we compile these files separately. -->
@@ -474,7 +477,7 @@
<copy file="${kotlin-home}/lib/kotlin-stdlib-js.jar" tofile="${kotlin-home}/lib/kotlin-jslib.jar" />
</target>
<target name="pack-js-stdlib-sources">
<target name="pack-js-stdlib-sources" depends="js-stdlib-preprocess">
<jar destfile="${kotlin-home}/lib/kotlin-stdlib-js-sources.jar" duplicate="fail">
<resources refid="js.lib.files" />
<fileset refid="kotlin.builtin.files" />
@@ -586,7 +589,6 @@
<zipfileset src="${idea.sdk}/lib/oromatcher.jar"/>
<zipfileset src="${idea.sdk}/jps/jps-model.jar"/>
<zipfileset src="${dependencies}/jline.jar"/>
<zipfileset src="${dependencies}/cli-parser-1.1.2.jar"/>
<zipfileset src="${protobuf.jar}"/>
<manifest>
@@ -617,13 +619,6 @@
</target>
<target name="compiler">
<taskdef resource="proguard/ant/task.properties">
<classpath>
<pathelement path="${dependencies}/proguard.jar"/>
<pathelement path="${dependencies}/proguard-anttask.jar"/>
</classpath>
</taskdef>
<cleandir dir="${output}/classes/compiler"/>
<javac2 destdir="${output}/classes/compiler" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false"
@@ -645,17 +640,32 @@
unless:true="${shrink}" />
<sequential if:true="${shrink}">
<shrink configuration="${basedir}/compiler/compiler.pro"/>
</sequential>
<pack-compiler-for-maven/>
</target>
<macrodef name="shrink">
<attribute name="configuration"/>
<sequential>
<taskdef resource="proguard/ant/task.properties">
<classpath>
<pathelement path="${dependencies}/proguard.jar"/>
<pathelement path="${dependencies}/proguard-anttask.jar"/>
</classpath>
</taskdef>
<available property="rtjar" value="${java.home}/lib/rt.jar" file="${java.home}/lib/rt.jar"/>
<available property="rtjar" value="${java.home}/../Classes/classes.jar" file="${java.home}/../Classes/classes.jar"/>
<available property="jssejar" value="${java.home}/lib/jsse.jar" file="${java.home}/lib/jsse.jar"/>
<available property="jssejar" value="${java.home}/../Classes/jsse.jar" file="${java.home}/../Classes/jsse.jar"/>
<proguard configuration="${basedir}/compiler/compiler.pro"/>
<proguard configuration="@{configuration}"/>
</sequential>
<pack-compiler-for-maven/>
</target>
</macrodef>
<macrodef name="pack-compiler-for-maven">
<sequential>
@@ -756,7 +766,7 @@
<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.daemon-client}"/>
<attribute name="Implementation-Title" value="${manifest.impl.title.kotlin.daemon.client}"/>
<attribute name="Implementation-Version" value="${build.number}"/>
</manifest>
</jar>
@@ -776,6 +786,27 @@
</jar>
</target>
<target name="compiler-client-embeddable">
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="dependencies/jarjar.jar"/>
<jarjar jarfile="${output}/kotlin-compiler-client-embeddable-before-shrink.jar">
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
<zipfileset src="${kotlin-home}/lib/kotlin-daemon-client.jar"/>
<fileset dir="${output}/classes/compiler"
includes="org/jetbrains/kotlin/daemon/common/** org/jetbrains/kotlin/cli/common/messages/CompilerMessage* org/jetbrains/kotlin/cli/common/messages/Message* org/jetbrains/kotlin/cli/common/repl/**"/>
<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.compiler.client,embeddable}"/>
<attribute name="Implementation-Version" value="${build.number}"/>
<attribute name="Class-Path" value="kotlin-stdlib.jar"/>
</manifest>
</jarjar>
<shrink configuration="${basedir}/compiler/compiler-client.pro"/>
</target>
<target name="android-extensions-compiler">
<cleandir dir="${output}/classes/android-extensions/android-extensions-compiler"/>
<javac2 destdir="${output}/classes/android-extensions/android-extensions-compiler" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
@@ -868,6 +899,29 @@
</jar>
</target>
<target name="source-sections-compiler-plugin">
<cleandir dir="${output}/classes/source-sections-compiler-plugin"/>
<javac2 destdir="${output}/classes/source-sections-compiler-plugin" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
<withKotlin modulename="source-sections">
<compilerarg value="-version"/>
</withKotlin>
<skip pattern="kotlin/Metadata"/>
<src>
<pathelement path="plugins/source-sections/source-sections-compiler/src"/>
</src>
<classpath>
<pathelement path="${idea.sdk}/core/intellij-core.jar"/>
<pathelement path="${kotlin-home}/lib/kotlin-compiler.jar"/>
</classpath>
</javac2>
<jar destfile="${kotlin-home}/lib/source-sections-compiler-plugin.jar">
<fileset dir="${output}/classes/source-sections-compiler-plugin"/>
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
<fileset dir="${basedir}/plugins/source-sections/source-sections-compiler/src" includes="META-INF/services/**"/>
</jar>
</target>
<target name="annotation-processing-under-jdk8">
<property environment="env"/>
@@ -1005,7 +1059,7 @@
</java>
<javac2 srcdir="${toString:src.dirset}" destdir="@{output}" debug="true" debuglevel="lines,vars,source"
includeAntRuntime="false" source="${java.target}" target="${java.target}">
includeAntRuntime="false" source="${java.target.1.6}" target="${java.target.1.6}">
<skip pattern="kotlin/Metadata"/>
<classpath>
<path refid="classpath.path"/>
@@ -1024,13 +1078,13 @@
<sequential>
<java classname="org.jetbrains.kotlin.preloading.Preloader" failonerror="true" fork="true" maxmemory="${max.heap.size.for.forked.jvm}">
<classpath>
<pathelement location="${kotlin-home}/lib/kotlin-preloader.jar"/>
<pathelement location="${bootstrap.compiler.home}/lib/kotlin-preloader.jar"/>
</classpath>
<assertions>
<enable/>
</assertions>
<arg value="-cp"/>
<arg value="${kotlin-home}/lib/kotlin-compiler.jar"/>
<arg value="${bootstrap.compiler.home}/lib/kotlin-compiler.jar"/>
<arg value="org.jetbrains.kotlin.preprocessor.PreprocessorCLI"/>
<arg value="@{src}"/>
<arg value="@{output}"/>
@@ -1224,11 +1278,10 @@
</manifest>
</jar>
<delete file="${output}/kotlin-reflect-jarjar.jar" failonerror="false"/>
<sequential if:true="${obfuscate.reflect}">
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="dependencies/jarjar.jar"/>
<jarjar jarfile="${output}/kotlin-reflect-jarjar.jar" filesonly="true" filesetmanifest="merge">
<delete file="${output}/kotlin-reflect-after-jarjar.jar" failonerror="false"/>
<jarjar jarfile="${output}/kotlin-reflect-after-jarjar.jar" filesonly="true" filesetmanifest="merge">
<zipfileset src="${output}/kotlin-reflect-before-jarjar.jar"/>
<rule pattern="org.jetbrains.kotlin.**" result="kotlin.reflect.jvm.internal.impl.@1"/>
<rule pattern="javax.inject.**" result="kotlin.reflect.jvm.internal.impl.javax.inject.@1"/>
@@ -1239,17 +1292,18 @@
<compilerarg value="-script"/>
<compilerarg value="kotlin/Metadata"/> <!-- Annotation to strip -->
<compilerarg value="kotlin/reflect/jvm/internal/impl/.*"/> <!-- Classes to strip from -->
<compilerarg value="${output}/kotlin-reflect-jarjar.jar"/>
<compilerarg value="${kotlin-home}/lib/kotlin-reflect.jar"/>
<compilerarg value="${output}/kotlin-reflect-after-jarjar.jar"/>
<compilerarg value="${output}/kotlin-reflect-before-proguard.jar"/>
<classpath>
<pathelement location="${idea.sdk}/lib/asm-all.jar"/>
</classpath>
</kotlinc>
<shrink configuration="${basedir}/core/reflection.jvm/reflection.pro"/>
</sequential>
<sequential unless:true="${obfuscate.reflect}">
<echo message="Obfuscation of kotlin-reflect is disabled"/>
<copy file="${output}/kotlin-reflect-before-jarjar.jar" tofile="${output}/kotlin-reflect-jarjar.jar" overwrite="true"/>
<copy file="${output}/kotlin-reflect-before-jarjar.jar" tofile="${kotlin-home}/lib/kotlin-reflect.jar" overwrite="true"/>
</sequential>
</target>
@@ -1330,11 +1384,11 @@
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,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,source-sections-compiler-plugin,annotation-processing-under-jdk8,daemon-client,kotlin-build-common-test"
description="Builds redistributables from sources"/>
<target name="dist-quick"
depends="clean,init,prepare-dist,preloader,serialize-builtins,compiler-quick,ant-tools,runtime,kotlin-js-stdlib,android-extensions-compiler,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,annotation-processing-under-jdk8"
depends="clean,init,prepare-dist,preloader,serialize-builtins,compiler-quick,ant-tools,runtime,kotlin-js-stdlib,android-extensions-compiler,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,source-sections-compiler-plugin,annotation-processing-under-jdk8"
description="Builds everything, but classes are reused from project out dir, doesn't run proguard and javadoc"/>
<target name="dist-quick-compiler-only"

View File

@@ -29,8 +29,8 @@ public class AndroidJpsBuildTestCase extends BaseKotlinJpsBuildTestCase {
public void doTest() {
initProject();
rebuildAll();
makeAll().assertSuccessful();
rebuildAllModules();
buildAllModules().assertSuccessful();
}
@Override

View File

@@ -91,7 +91,7 @@ object CodegenUtil {
else if (traitMember is PropertyDescriptor) {
for (traitAccessor in traitMember.accessors) {
for (inheritedAccessor in (copy as PropertyDescriptor).accessors) {
if (inheritedAccessor.javaClass == traitAccessor.javaClass) { // same accessor kind
if (inheritedAccessor::class.java == traitAccessor::class.java) { // same accessor kind
result.put(traitAccessor, inheritedAccessor)
}
}

View File

@@ -103,5 +103,5 @@ abstract class DataClassMethodGenerator(private val declaration: KtClassOrObject
.map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! }
private val primaryConstructorParameters: List<KtParameter>
get() = (declaration as? KtClass)?.getPrimaryConstructorParameters().orEmpty()
get() = (declaration as? KtClass)?.primaryConstructorParameters.orEmpty()
}

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
@@ -31,7 +32,12 @@ abstract class ArgumentGenerator {
*
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
*/
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallArgs {
open fun generate(
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
// may be null for a constructor of an object literal
calleeDescriptor: CallableDescriptor?
): DefaultCallArgs {
assert(valueArgumentsByIndex.size == actualArgs.size) {
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}"
}
@@ -48,7 +54,8 @@ abstract class ArgumentGenerator {
}
}
val defaultArgs = DefaultCallArgs(valueArgumentsByIndex.size)
// Use unwrapped version, because additional synthetic parameters can't have default values
val defaultArgs = DefaultCallArgs(calleeDescriptor?.unwrapFrontendVersion()?.valueParameters?.size ?: 0)
for (argumentWithDeclIndex in actualArgsWithDeclIndex) {
val argument = argumentWithDeclIndex.arg

View File

@@ -770,6 +770,7 @@ public class AsmUtil {
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
if (left == Type.CHAR_TYPE || right == Type.CHAR_TYPE) return Type.CHAR_TYPE;
return Type.INT_TYPE;
}

View File

@@ -210,7 +210,12 @@ class NumberCompare(
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int {
when (operandType) {
// Opcode takes one int operand from the stack
assert(opcode in IFEQ..IFLE) {
"Opcode for comparing must be in range ${IFEQ..IFLE}, but $opcode was found"
}
return when (operandType) {
Type.FLOAT_TYPE, Type.DOUBLE_TYPE -> {
if (opToken == KtTokens.GT || opToken == KtTokens.GTEQ) {
v.cmpl(operandType)
@@ -218,17 +223,19 @@ class NumberCompare(
else {
v.cmpg(operandType)
}
opcode
}
Type.LONG_TYPE -> {
v.lcmp()
opcode
}
else -> {
return opcode + (IF_ICMPEQ - IFEQ)
opcode + (IF_ICMPEQ - IFEQ)
}
}
return opcode
}
companion object {
fun getNumberCompareOpcode(opToken: IElementType): Int {
return when (opToken) {
@@ -262,4 +269,4 @@ class ObjectCompare(
}
}
}
}
}

View File

@@ -17,10 +17,13 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.ValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.List;
@@ -53,11 +56,12 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
@Override
public DefaultCallArgs generate(
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
@NotNull List<? extends ResolvedValueArgument> valueArgs
@NotNull List<? extends ResolvedValueArgument> valueArgs,
@Nullable CallableDescriptor calleeDescriptor
) {
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
this.codegen.setShouldMarkLineNumbers(false);
DefaultCallArgs defaultArgs = super.generate(valueArgumentsByIndex, valueArgs);
DefaultCallArgs defaultArgs = super.generate(valueArgumentsByIndex, valueArgs, calleeDescriptor);
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
return defaultArgs;
}
@@ -84,7 +88,9 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
protected void generateVararg(int i, @NotNull VarargValueArgument argument) {
ValueParameterDescriptor parameter = valueParameters.get(i);
Type type = valueParameterTypes.get(i);
codegen.genVarargs(argument, parameter.getType());
// Upper bound for type of vararg parameter should always have a form of 'Array<out T>',
// while its lower bound may be Nothing-typed after approximation
codegen.genVarargs(argument, FlexibleTypesKt.upperIfFlexible(parameter.getType()));
callGenerator.afterParameterPut(type, null, i);
}

View File

@@ -77,9 +77,13 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
}
}
generatePrimaryConstructorProperties();
generateConstructors();
generateDefaultImplsIfNeeded();
boolean generateNonClassMembers = shouldGenerateNonClassMembers();
if (generateNonClassMembers) {
generatePrimaryConstructorProperties();
generateConstructors();
generateDefaultImplsIfNeeded();
}
// Generate _declared_ companions
for (KtObjectDeclaration companion : companions) {
@@ -92,23 +96,30 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
}
if (!DescriptorUtils.isInterface(descriptor)) {
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
if (memberDescriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
if (!member.getKind().isReal() && ImplKt.findInterfaceImplementation(member) == null) {
if (member instanceof FunctionDescriptor) {
functionCodegen.generateBridges((FunctionDescriptor) member);
if (generateNonClassMembers) {
generateBridges();
}
}
private void generateBridges() {
if (DescriptorUtils.isInterface(descriptor)) {
return;
}
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
if (memberDescriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
if (!member.getKind().isReal() && ImplKt.findInterfaceImplementation(member) == null) {
if (member instanceof FunctionDescriptor) {
functionCodegen.generateBridges((FunctionDescriptor) member);
}
else if (member instanceof PropertyDescriptor) {
PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter();
if (getter != null) {
functionCodegen.generateBridges(getter);
}
else if (member instanceof PropertyDescriptor) {
PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter();
if (getter != null) {
functionCodegen.generateBridges(getter);
}
PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter();
if (setter != null) {
functionCodegen.generateBridges(setter);
}
PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter();
if (setter != null) {
functionCodegen.generateBridges(setter);
}
}
}
@@ -116,6 +127,11 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
}
}
private boolean shouldGenerateNonClassMembers() {
return !(myClass instanceof KtClassOrObject) ||
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) myClass);
}
protected void generateConstructors() {
}
@@ -130,7 +146,9 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
protected void generateDeclaration(KtDeclaration declaration) {
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
genSimpleMember(declaration);
if (shouldGenerateNonClassMembers()) {
genSimpleMember(declaration);
}
}
else if (declaration instanceof KtClassOrObject) {
if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {

View File

@@ -55,20 +55,12 @@ public class ClassBuilderFactories {
throw new IllegalStateException();
}
};
public static ClassBuilderFactory TEST_KAPT3 = new TestClassBuilderFactory(false) {
@NotNull
@Override
public ClassBuilderMode getClassBuilderMode() {
return ClassBuilderMode.KAPT3;
}
};
public static ClassBuilderFactory TEST = new TestClassBuilderFactory(false);
public static ClassBuilderFactory TEST_WITH_SOURCE_RETENTION_ANNOTATIONS = new TestClassBuilderFactory(true);
private static class TestClassBuilderFactory implements ClassBuilderFactory {
public static class TestClassBuilderFactory implements ClassBuilderFactory {
private final boolean generateSourceRetentionAnnotations;
public TestClassBuilderFactory(boolean generateSourceRetentionAnnotations) {

View File

@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.TestOnly;
public class ClassBuilderMode {
public final boolean generateBodies;
public final boolean generateMetadata;
@@ -73,4 +75,11 @@ public class ClassBuilderMode {
/* metadata = */ true,
/* sourceRetention = */ true,
/* generateMultiFileFacadePartClasses = */ true);
@TestOnly
public final static ClassBuilderMode LIGHT_ANALYSIS_FOR_TESTS = new ClassBuilderMode(
/* bodies = */ false,
/* metadata = */ true,
/* sourceRetention = */ false,
/* generateMultiFileFacadePartClasses = */ true);
}

View File

@@ -82,7 +82,7 @@ public class ClassFileFactory implements OutputFileCollection {
return answer;
}
void done() {
public void done() {
if (!isDone) {
isDone = true;
writeModuleMappings();

View File

@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -55,7 +54,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
contextKind: OwnerKind,
classOrObject: KtPureClassOrObject
) {
val methodElement = classOrObject.getPrimaryConstructor() ?: classOrObject
val methodElement = classOrObject.primaryConstructor ?: classOrObject
if (generateOverloadsIfNeeded(methodElement, constructorDescriptor, constructorDescriptor, contextKind, classBuilder, memberCodegen)) {
return
@@ -129,12 +128,14 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
) {
val typeMapper = state.typeMapper
val isStatic = AsmUtil.isStaticMethod(contextKind, functionDescriptor)
val flags = AsmUtil.getCommonCallableFlags(functionDescriptor) or
(if (isStatic) Opcodes.ACC_STATIC else 0) or
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0)
val baseMethodFlags = AsmUtil.getCommonCallableFlags(functionDescriptor) and Opcodes.ACC_VARARGS.inv()
val remainingParameters = getRemainingParameters(functionDescriptor.original, substituteCount)
val signature = typeMapper.mapSignature(functionDescriptor, contextKind, remainingParameters, false)
val flags =
baseMethodFlags or
(if (isStatic) Opcodes.ACC_STATIC else 0) or
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0) or
(if (remainingParameters.lastOrNull()?.varargElementType != null) Opcodes.ACC_VARARGS else 0)
val signature = typeMapper.mapSignatureWithCustomParameters(functionDescriptor, contextKind, remainingParameters, false)
val mv = classBuilder.newMethod(OtherOrigin(methodElement, functionDescriptor), flags,
signature.asmMethod.name,
signature.asmMethod.descriptor,
@@ -250,7 +251,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
val classDescriptor = constructorDescriptor.constructedClass
if (classDescriptor.kind != ClassKind.CLASS) return false
if (classOrObject.isLocal()) return false
if (classOrObject.isLocal) return false
if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false
@@ -264,6 +265,6 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
}
private fun hasSecondaryConstructorsWithNoParameters(klass: KtClass) =
klass.getSecondaryConstructors().any { it.valueParameters.isEmpty() }
klass.secondaryConstructors.any { it.valueParameters.isEmpty() }
}

View File

@@ -33,10 +33,10 @@ abstract class DelegatingClassBuilderFactory(
abstract override fun newClassBuilder(origin: JvmDeclarationOrigin): DelegatingClassBuilder
override fun asBytes(builder: ClassBuilder?): ByteArray? {
return delegate.asBytes((builder as DelegatingClassBuilder).getDelegate())
return delegate.asBytes((builder as DelegatingClassBuilder).delegate)
}
override fun asText(builder: ClassBuilder?): String? {
return delegate.asText((builder as DelegatingClassBuilder).getDelegate())
return delegate.asText((builder as DelegatingClassBuilder).delegate)
}
}

View File

@@ -1709,7 +1709,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ArgumentGenerator argumentGenerator =
new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes);
argumentGenerator.generate(valueArguments, valueArguments);
argumentGenerator.generate(valueArguments, valueArguments, null);
}
Collection<ClassConstructorDescriptor> constructors = classDescriptor.getConstructors();
@@ -1919,11 +1919,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return asmType(varType);
}
private static boolean isSharedVarType(@NotNull Type type) {
return type.getSort() == Type.OBJECT && type.getInternalName().startsWith(REF_TYPE_PREFIX);
}
private void putDescriptorIntoFrameMap(@NotNull KtElement statement) {
if (statement instanceof KtDestructuringDeclaration) {
KtDestructuringDeclaration multiDeclaration = (KtDestructuringDeclaration) statement;
@@ -2867,7 +2862,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
DefaultCallArgs defaultArgs =
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()));
argumentGenerator.generate(
valueArguments,
new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()),
resolvedCall.getResultingDescriptor()
);
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
tailRecursionCodegen.generateTailRecursion(resolvedCall);
@@ -3192,7 +3191,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
if (isSingleton) {
if (calleeContainingClass.equals(context.getThisDescriptor()) &&
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getContextDescriptor())) {
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getFunctionDescriptor())) {
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
}
else if (isEnumEntry(calleeContainingClass)) {
@@ -4316,6 +4315,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private static ReceiverValue getConstructorReceiver(@NotNull ResolvedCall<?> resolvedCall) {
CallableDescriptor constructor = resolvedCall.getResultingDescriptor();
if (constructor.getExtensionReceiverParameter() != null) {
// see comment on `withDispatchReceiver` parameter in
// org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl.Companion.createIfAvailable
assert constructor instanceof TypeAliasConstructorDescriptor :
"Only type alias constructor can have an extension receiver: " + constructor;
return resolvedCall.getExtensionReceiver();
@@ -4907,7 +4908,8 @@ The "returned" value of try expression with no finally is either the last expres
public NameGenerator getInlineNameGenerator() {
NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator();
Name name = context.getContextDescriptor().getName();
return nameGenerator.subGenerator((name.isSpecial() ? "$special" : name.asString()) + "$$inlined" );
String inlinedName = name.isSpecial() ? InlineCodegenUtil.SPECIAL_TRANSFORMATION_NAME : name.asString();
return nameGenerator.subGenerator(inlinedName + InlineCodegenUtil.INLINE_CALL_TRANSFORMATION_SUFFIX);
}
public Type getReturnType() {

View File

@@ -231,7 +231,7 @@ public class FunctionCodegen {
boolean staticInCompanionObject = CodegenUtilKt.isJvmStaticInCompanionObject(functionDescriptor);
if (staticInCompanionObject) {
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
parentBodyCodegen.addAdditionalTask(new JvmStaticGenerator(functionDescriptor, origin, state, parentBodyCodegen));
parentBodyCodegen.addAdditionalTask(new JvmStaticInCompanionObjectGenerator(functionDescriptor, origin, state, parentBodyCodegen));
}
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind, state)) {
@@ -256,7 +256,8 @@ public class FunctionCodegen {
else if (staticInCompanionObject) {
// native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
mv.visitCode();
FunctionDescriptor staticFunctionDescriptor = JvmStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
FunctionDescriptor staticFunctionDescriptor = JvmStaticInCompanionObjectGenerator
.createStaticFunctionDescriptor(functionDescriptor);
Method accessorMethod =
typeMapper.mapAsmMethod(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
@@ -919,17 +920,23 @@ public class FunctionCodegen {
// enum constructors have two additional synthetic parameters which somewhat complicate this task
AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType());
if (state.getClassBuilderMode().generateBodies) {
if (this.owner instanceof MultifileClassFacadeContext) {
mv.visitCode();
generateFacadeDelegateMethodBody(mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
if (!state.getClassBuilderMode().generateBodies) {
if (this.owner instanceof MultifileClassFacadeContext)
endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
}
else {
mv.visitCode();
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
else
endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
}
return;
}
if (this.owner instanceof MultifileClassFacadeContext) {
mv.visitCode();
generateFacadeDelegateMethodBody(mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
}
else {
mv.visitCode();
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
}
}

View File

@@ -37,6 +37,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.*;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject;
public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased {
private final ResolvedCall<?> resolvedCall;
private final FunctionDescriptor referencedFunction;
@@ -146,6 +148,12 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
(referencedFunction.getExtensionReceiverParameter() != null ? 1 : 0) -
(receiverType != null ? 1 : 0);
if (receivers < 0 && referencedFunction instanceof ConstructorDescriptor && isObject(referencedFunction.getContainingDeclaration().getContainingDeclaration())) {
//reference to object nested class
//TODO: seems problem should be fixed on frontend side (note that object instance are captured by generated class)
receivers = 0;
}
List<ValueParameterDescriptor> parameters = CollectionsKt.drop(functionDescriptor.getValueParameters(), receivers);
for (int i = 0; i < parameters.size(); i++) {
ValueParameterDescriptor parameter = parameters.get(i);

View File

@@ -88,6 +88,7 @@ import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.
import static org.jetbrains.kotlin.types.Variance.INVARIANT;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isLocalFunction;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
import static org.jetbrains.org.objectweb.asm.Type.getObjectType;
public class ImplementationBodyCodegen extends ClassBodyCodegen {
private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
@@ -113,7 +114,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
boolean isLocal
) {
super(aClass, context, v, state, parentCodegen);
this.classAsmType = typeMapper.mapClass(descriptor);
this.classAsmType = getObjectType(typeMapper.classInternalName(descriptor));
this.isLocal = isLocal;
delegationFieldsInfo = getDelegationFieldsInfo(myClass.getSuperTypeListEntries());
}
@@ -127,55 +128,47 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
boolean isAbstract = false;
boolean isInterface = false;
boolean isFinal = false;
boolean isStatic;
boolean isAnnotation = false;
boolean isEnum = false;
ClassKind kind = descriptor.getKind();
if (kind == ClassKind.OBJECT) {
isStatic = isCompanionObject(descriptor);
isFinal = true;
Modality modality = descriptor.getModality();
if (modality == Modality.ABSTRACT || modality == Modality.SEALED) {
isAbstract = true;
}
else {
Modality modality = descriptor.getModality();
if (modality == Modality.ABSTRACT || modality == Modality.SEALED) {
isAbstract = true;
}
if (kind == ClassKind.INTERFACE) {
isAbstract = true;
isInterface = true;
}
else if (kind == ClassKind.ANNOTATION_CLASS) {
isAbstract = true;
isInterface = true;
isAnnotation = true;
}
else if (kind == ClassKind.ENUM_CLASS) {
isAbstract = hasAbstractMembers(descriptor);
isEnum = true;
}
if (kind == ClassKind.INTERFACE) {
isAbstract = true;
isInterface = true;
}
else if (kind == ClassKind.ANNOTATION_CLASS) {
isAbstract = true;
isInterface = true;
isAnnotation = true;
}
else if (kind == ClassKind.ENUM_CLASS) {
isAbstract = hasAbstractMembers(descriptor);
isEnum = true;
}
if (modality != Modality.OPEN && !isAbstract) {
// Light-class mode: Do not make enum classes final since PsiClass corresponding to enum is expected to be inheritable from
isFinal = !(kind == ClassKind.ENUM_CLASS && !state.getClassBuilderMode().generateBodies);
}
isStatic = !descriptor.isInner();
if (modality != Modality.OPEN && !isAbstract) {
isFinal = kind == ClassKind.OBJECT ||
// Light-class mode: Do not make enum classes final since PsiClass corresponding to enum is expected to be inheritable from
!(kind == ClassKind.ENUM_CLASS && !state.getClassBuilderMode().generateBodies);
}
int access = 0;
if (!state.getClassBuilderMode().generateBodies && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
// !ClassBuilderMode.generateBodies means we are generating light classes & looking at a nested or inner class
// Light class generation is implemented so that Cls-classes only read bare code of classes,
// without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY)
// Thus we must write full accessibility flags on inner classes in this mode
access |= getVisibilityAccessFlag(descriptor);
// Same for STATIC
if (isStatic) {
if (!descriptor.isInner()) {
access |= ACC_STATIC;
}
}
@@ -332,7 +325,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (String kotlinMarkerInterface : kotlinMarkerInterfaces) {
sw.writeInterface();
sw.writeAsmType(Type.getObjectType(kotlinMarkerInterface));
sw.writeAsmType(getObjectType(kotlinMarkerInterface));
sw.writeInterfaceEnd();
}
@@ -1207,9 +1200,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
else if (descriptor instanceof VariableDescriptor) {
if (descriptor.getContainingDeclaration() instanceof ConstructorDescriptor) {
ClassDescriptor classDescriptor =
(ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration();
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration instanceof ConstructorDescriptor) {
ClassDescriptor classDescriptor = ((ConstructorDescriptor) containingDeclaration).getConstructedClass();
if (classDescriptor == ImplementationBodyCodegen.this.descriptor) return;
}
lookupInContext(descriptor);

View File

@@ -1,101 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class JvmStaticGenerator(
val descriptor: FunctionDescriptor,
val declarationOrigin: JvmDeclarationOrigin,
val state: GenerationState,
parentBodyCodegen: ImplementationBodyCodegen
) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> {
private val typeMapper = state.typeMapper
init {
parentBodyCodegen.getContext().accessibleDescriptor(JvmCodegenUtil.getDirectMember(descriptor), null)
}
override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) {
val staticFunctionDescriptor = createStaticFunctionDescriptor(descriptor)
val originElement = declarationOrigin.element
codegen.functionCodegen.generateMethod(
Synthetic(originElement, staticFunctionDescriptor),
staticFunctionDescriptor,
object : FunctionGenerationStrategy.CodegenBased(state) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
val iv = codegen.v
val classDescriptor = descriptor.containingDeclaration as ClassDescriptor
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)
singletonValue.put(singletonValue.type, iv)
var index = 0
val asmMethod = signature.asmMethod
for (paramType in asmMethod.argumentTypes) {
iv.load(index, paramType)
index += paramType.size
}
if (descriptor is PropertyAccessorDescriptor) {
val propertyValue = codegen.intermediateValueForProperty(descriptor.correspondingProperty, false, null, StackValue.none())
if (descriptor is PropertyGetterDescriptor) {
propertyValue.put(signature.returnType, iv)
}
else {
propertyValue.store(StackValue.onStack(propertyValue.type), iv, true)
}
}
else {
val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod(
codegen.context.accessibleDescriptor(descriptor, /* superCallTarget = */ null),
false
)
syntheticOrOriginalMethod.genInvokeInstruction(iv)
}
iv.areturn(asmMethod.returnType)
}
}
)
if (originElement is KtNamedFunction) {
codegen.functionCodegen.generateOverloadsWithDefaultValues(originElement, staticFunctionDescriptor, descriptor)
}
}
companion object {
@JvmStatic
fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.correspondingProperty else descriptor
val copies = CodegenUtil.copyFunctions(
memberDescriptor,
memberDescriptor,
descriptor.containingDeclaration.containingDeclaration!!,
descriptor.modality,
descriptor.visibility,
CallableMemberDescriptor.Kind.SYNTHESIZED,
false
)
val staticFunctionDescriptor = copies[descriptor]!!
return staticFunctionDescriptor
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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.codegen
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class JvmStaticInCompanionObjectGenerator(
val descriptor: FunctionDescriptor,
val declarationOrigin: JvmDeclarationOrigin,
val state: GenerationState,
parentBodyCodegen: ImplementationBodyCodegen
) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> {
private val typeMapper = state.typeMapper
init {
parentBodyCodegen.getContext().accessibleDescriptor(JvmCodegenUtil.getDirectMember(descriptor), null)
}
override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) {
val staticFunctionDescriptor = createStaticFunctionDescriptor(descriptor)
val originElement = declarationOrigin.element
codegen.functionCodegen.generateMethod(
Synthetic(originElement, staticFunctionDescriptor),
staticFunctionDescriptor,
object : FunctionGenerationStrategy.CodegenBased(state) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
val iv = codegen.v
val classDescriptor = descriptor.containingDeclaration as ClassDescriptor
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)
singletonValue.put(singletonValue.type, iv)
var index = 0
val asmMethod = signature.asmMethod
for (paramType in asmMethod.argumentTypes) {
iv.load(index, paramType)
index += paramType.size
}
if (descriptor is PropertyAccessorDescriptor) {
val propertyValue = codegen.intermediateValueForProperty(descriptor.correspondingProperty, false, null, StackValue.none())
if (descriptor is PropertyGetterDescriptor) {
propertyValue.put(signature.returnType, iv)
}
else {
propertyValue.store(StackValue.onStack(propertyValue.type), iv, true)
}
}
else {
val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod(
codegen.context.accessibleDescriptor(descriptor, /* superCallTarget = */ null),
false
)
syntheticOrOriginalMethod.genInvokeInstruction(iv)
}
iv.areturn(asmMethod.returnType)
}
}
)
if (originElement is KtNamedFunction) {
codegen.functionCodegen.generateOverloadsWithDefaultValues(originElement, staticFunctionDescriptor, descriptor)
}
}
companion object {
@JvmStatic
fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.correspondingProperty else descriptor
val copies = CodegenUtil.copyFunctions(
memberDescriptor,
memberDescriptor,
descriptor.containingDeclaration.containingDeclaration!!,
descriptor.modality,
descriptor.visibility,
CallableMemberDescriptor.Kind.SYNTHESIZED,
false
)
val staticFunctionDescriptor = copies[descriptor]!!
return staticFunctionDescriptor
}
}
}

View File

@@ -127,7 +127,10 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
generateBody();
generateSyntheticParts();
if (!(element instanceof KtClassOrObject) ||
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) element)) {
generateSyntheticParts();
}
if (state.getClassBuilderMode().generateMetadata) {
generateKotlinMetadataAnnotation();
@@ -342,17 +345,19 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
writeInnerClass(innerClass, typeMapper, v);
if (!ErrorUtils.isError(innerClass)) {
writeInnerClass(innerClass, typeMapper, v);
}
}
public static void writeInnerClass(@NotNull ClassDescriptor innerClass, @NotNull KotlinTypeMapper typeMapper, @NotNull ClassBuilder v) {
DeclarationDescriptor containing = innerClass.getContainingDeclaration();
String outerClassInternalName = null;
if (containing instanceof ClassDescriptor) {
outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
outerClassInternalName = typeMapper.classInternalName((ClassDescriptor) containing);
}
String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
String innerClassInternalName = typeMapper.classInternalName(innerClass);
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
}
@@ -499,10 +504,11 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
int indexOfDelegatedProperty = PropertyCodegen.indexOfDelegatedProperty(property);
StackValue delegateValue = PropertyCodegen.invokeDelegatedPropertyConventionMethodWithReceiver(
codegen, typeMapper, provideDelegateResolvedCall, indexOfDelegatedProperty, 1, provideDelegateReceiver);
codegen, typeMapper, provideDelegateResolvedCall, indexOfDelegatedProperty, 1,
provideDelegateReceiver, propertyDescriptor
);
propValue.store(delegateValue, codegen.v);
}
protected boolean shouldInitializeProperty(@NotNull KtProperty property) {
@@ -590,7 +596,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
if (delegatedProperties.isEmpty()) return;
v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
v.newField(NO_ORIGIN, ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
"[" + K_PROPERTY_TYPE, null, null);
if (!state.getClassBuilderMode().generateBodies) return;

View File

@@ -176,7 +176,7 @@ class MultifileClassPartCodegen(
}
val serializer = DescriptorSerializer.createTopLevel(JvmSerializerExtension(v.serializationBindings, state))
val packageProto = serializer.packagePartProto(members).build()
val packageProto = serializer.packagePartProto(packageFragment.fqName, members).build()
val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0

View File

@@ -129,7 +129,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
final DescriptorSerializer serializer =
DescriptorSerializer.createTopLevel(new JvmSerializerExtension(v.getSerializationBindings(), state));
final ProtoBuf.Package packageProto = serializer.packagePartProto(members).build();
final ProtoBuf.Package packageProto = serializer.packagePartProto(element.getPackageFqName(), members).build();
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.FILE_FACADE, 0, new Function1<AnnotationVisitor, Unit>() {
@Override

View File

@@ -188,7 +188,7 @@ public class PropertyCodegen {
if (isCompanionObject(descriptor.getContainingDeclaration())) return true;
// Non-const properties from multifile classes have accessors regardless of visibility
if (!descriptor.isConst() && JvmFileClassUtilKt.isInsideJvmMultifileClassFile(declaration)) return true;
if (isNonConstTopLevelPropertyInMultifileClass(declaration, descriptor)) return true;
// Private class properties have accessors only in cases when those accessors are non-trivial
if (Visibilities.isPrivate(descriptor.getVisibility())) {
@@ -198,6 +198,15 @@ public class PropertyCodegen {
return true;
}
private static boolean isNonConstTopLevelPropertyInMultifileClass(
@NotNull KtProperty declaration,
@NotNull PropertyDescriptor descriptor
) {
return !descriptor.isConst() &&
descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor &&
JvmFileClassUtilKt.isInsideJvmMultifileClassFile(declaration);
}
private static boolean areAccessorsNeededForPrimaryConstructorProperty(
@NotNull PropertyDescriptor descriptor
) {
@@ -534,7 +543,7 @@ public class PropertyCodegen {
StackValue.Property receiver = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
return invokeDelegatedPropertyConventionMethodWithReceiver(
codegen, typeMapper, resolvedCall, indexInPropertyMetadataArray, propertyMetadataArgumentIndex,
receiver
receiver, propertyDescriptor
);
}
@@ -544,9 +553,12 @@ public class PropertyCodegen {
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
final int indexInPropertyMetadataArray,
int propertyMetadataArgumentIndex,
@Nullable StackValue receiver
@Nullable StackValue receiver,
@NotNull PropertyDescriptor propertyDescriptor
) {
final Type owner = getDelegatedPropertyMetadataOwner(codegen, typeMapper);
final Type owner = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor) ?
codegen.getState().getTypeMapper().mapOwner(propertyDescriptor) :
getDelegatedPropertyMetadataOwner(codegen, typeMapper);
codegen.tempVariables.put(
resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(),

View File

@@ -34,7 +34,7 @@ data class SourceInfo(val source: String, val pathOrCleanFQN: String, val linesI
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
return SourceInfo(element.getContainingKtFile().name, cleanedClassFqName, lineNumbers!!)
return SourceInfo(element.containingKtFile.name, cleanedClassFqName, lineNumbers!!)
}
}

View File

@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
@@ -281,60 +282,29 @@ public abstract class StackValue {
}
private static void box(Type type, Type toType, InstructionAdapter v) {
if (type == Type.BYTE_TYPE || toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME) && type == Type.INT_TYPE) {
v.cast(type, Type.BYTE_TYPE);
v.invokestatic(NULLABLE_BYTE_TYPE_NAME, "valueOf", "(B)L" + NULLABLE_BYTE_TYPE_NAME + ";", false);
}
else if (type == Type.SHORT_TYPE || toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME) && type == Type.INT_TYPE) {
v.cast(type, Type.SHORT_TYPE);
v.invokestatic(NULLABLE_SHORT_TYPE_NAME, "valueOf", "(S)L" + NULLABLE_SHORT_TYPE_NAME + ";", false);
}
else if (type == Type.LONG_TYPE || toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME) && type == Type.INT_TYPE) {
v.cast(type, Type.LONG_TYPE);
v.invokestatic(NULLABLE_LONG_TYPE_NAME, "valueOf", "(J)L" + NULLABLE_LONG_TYPE_NAME + ";", false);
}
else if (type == Type.INT_TYPE) {
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
}
else if (type == Type.BOOLEAN_TYPE) {
v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
}
else if (type == Type.CHAR_TYPE) {
v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
}
else if (type == Type.FLOAT_TYPE) {
v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
}
else if (type == Type.DOUBLE_TYPE) {
v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
if (type == Type.INT_TYPE) {
if (toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME)) {
type = Type.BYTE_TYPE;
}
else if (toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME)) {
type = Type.SHORT_TYPE;
}
else if (toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME)) {
type = Type.LONG_TYPE;
}
v.cast(Type.INT_TYPE, type);
}
Type boxedType = AsmUtil.boxType(type);
if (boxedType == type) return;
v.invokestatic(boxedType.getInternalName(), "valueOf", Type.getMethodDescriptor(boxedType, type), false);
coerce(boxedType, toType, v);
}
private static void unbox(Type type, InstructionAdapter v) {
if (type == Type.INT_TYPE) {
v.invokevirtual("java/lang/Number", "intValue", "()I", false);
}
else if (type == Type.BOOLEAN_TYPE) {
v.invokevirtual("java/lang/Boolean", "booleanValue", "()Z", false);
}
else if (type == Type.CHAR_TYPE) {
v.invokevirtual("java/lang/Character", "charValue", "()C", false);
}
else if (type == Type.SHORT_TYPE) {
v.invokevirtual("java/lang/Number", "shortValue", "()S", false);
}
else if (type == Type.LONG_TYPE) {
v.invokevirtual("java/lang/Number", "longValue", "()J", false);
}
else if (type == Type.BYTE_TYPE) {
v.invokevirtual("java/lang/Number", "byteValue", "()B", false);
}
else if (type == Type.FLOAT_TYPE) {
v.invokevirtual("java/lang/Number", "floatValue", "()F", false);
}
else if (type == Type.DOUBLE_TYPE) {
v.invokevirtual("java/lang/Number", "doubleValue", "()D", false);
}
private static void unbox(Type methodOwner, Type type, InstructionAdapter v) {
assert isPrimitive(type) : "Unboxing should be performed to primitive type, but " + type.getClassName();
v.invokevirtual(methodOwner.getInternalName(), type.getClassName() + "Value", "()" + type.getDescriptor(), false);
}
protected void coerceTo(@NotNull Type toType, @NotNull InstructionAdapter v) {
@@ -372,23 +342,12 @@ public abstract class StackValue {
}
}
else if (toType.getSort() == Type.ARRAY) {
if (fromType.getSort() == Type.ARRAY &&
fromType.getElementType().equals(AsmTypes.JAVA_CLASS_TYPE) && toType.equals(K_CLASS_ARRAY_TYPE)) {
wrapJavaClassesIntoKClasses(v);
}
else {
v.checkcast(toType);
}
v.checkcast(toType);
}
else if (toType.getSort() == Type.OBJECT) {
if (fromType.getSort() == Type.OBJECT || fromType.getSort() == Type.ARRAY) {
if (!toType.equals(OBJECT_TYPE)) {
if (fromType.equals(AsmTypes.JAVA_CLASS_TYPE) && toType.equals(AsmTypes.K_CLASS_TYPE)) {
wrapJavaClassIntoKClass(v);
}
else {
v.checkcast(toType);
}
v.checkcast(toType);
}
}
else {
@@ -396,20 +355,29 @@ public abstract class StackValue {
}
}
else if (fromType.getSort() == Type.OBJECT) {
//toType is primitive here
Type unboxedType = unboxPrimitiveTypeOrNull(fromType);
if (unboxedType != null) {
unbox(unboxedType, v);
unbox(fromType, unboxedType, v);
coerce(unboxedType, toType, v);
}
else {
Type numberType = getType(Number.class);
if (toType.getSort() == Type.BOOLEAN || (toType.getSort() == Type.CHAR && !numberType.equals(fromType))) {
coerce(fromType, boxType(toType), v);
else if (toType.getSort() == Type.BOOLEAN) {
coerce(fromType, BOOLEAN_WRAPPER_TYPE, v);
unbox(BOOLEAN_WRAPPER_TYPE, Type.BOOLEAN_TYPE, v);
}
else if (toType.getSort() == Type.CHAR) {
if (fromType.equals(NUMBER_TYPE)) {
unbox(NUMBER_TYPE, Type.INT_TYPE, v);
v.visitInsn(Opcodes.I2C);
}
else {
coerce(fromType, numberType, v);
coerce(fromType, CHARACTER_WRAPPER_TYPE, v);
unbox(CHARACTER_WRAPPER_TYPE, Type.CHAR_TYPE, v);
}
unbox(toType, v);
}
else {
coerce(fromType, NUMBER_TYPE, v);
unbox(NUMBER_TYPE, toType, v);
}
}
else {
@@ -883,7 +851,7 @@ public abstract class StackValue {
newReceiver.put(newReceiver.type, v);
callGenerator.processAndPutHiddenParameters(false);
defaultArgs = generator.generate(valueArguments, valueArguments);
defaultArgs = generator.generate(valueArguments, valueArguments, call.getResultingDescriptor());
}
private ArgumentGenerator createArgumentGenerator() {
@@ -1211,7 +1179,20 @@ public abstract class StackValue {
else {
getter.genInvokeInstruction(v);
}
coerce(getter.getReturnType(), type, v);
Type typeOfValueOnStack = getter.getReturnType();
if (DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
if (this.type.equals(K_CLASS_TYPE)) {
wrapJavaClassIntoKClass(v);
typeOfValueOnStack = K_CLASS_TYPE;
}
else if (this.type.equals(K_CLASS_ARRAY_TYPE)) {
wrapJavaClassesIntoKClasses(v);
typeOfValueOnStack = K_CLASS_ARRAY_TYPE;
}
}
coerce(typeOfValueOnStack, type, v);
KotlinType returnType = descriptor.getReturnType();
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) {
@@ -1378,9 +1359,7 @@ public abstract class StackValue {
default:
PrimitiveType primitiveType = AsmUtil.asmPrimitiveTypeToLangPrimitiveType(type);
if (primitiveType == null) throw new UnsupportedOperationException();
String typeName = primitiveType.getTypeName().getIdentifier();
return Type.getObjectType(REF_TYPE_PREFIX + typeName + "Ref");
return sharedTypeForPrimitive(primitiveType);
}
}

View File

@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeAsSequence
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import java.util.*
class BridgeForBuiltinSpecial<out Signature : Any>(
@@ -76,7 +75,7 @@ object BuiltinSpecialBridgesUtil {
else null
val commonBridges = reachableDeclarations.mapTo(LinkedHashSet<Signature>(), signatureByDescriptor)
commonBridges.removeAll(specialBridgesSignaturesInSuperClass + specialBridge?.from.singletonOrEmptyList())
commonBridges.removeAll(specialBridgesSignaturesInSuperClass + listOfNotNull(specialBridge?.from))
if (fake) {
for (overridden in function.overriddenDescriptors.map { it.original }) {

View File

@@ -40,7 +40,7 @@ private fun Iterable<PackageParts>.addCompiledParts(state: GenerationState): Lis
val incrementalCache = state.incrementalCacheForThisTarget ?: return this.toList()
val moduleMappingData = incrementalCache.getModuleMappingData() ?: return this.toList()
val mapping = ModuleMapping.create(moduleMappingData, "<incremental>")
val mapping = ModuleMapping.create(moduleMappingData, "<incremental>", state.deserializationConfiguration)
incrementalCache.getObsoletePackageParts().forEach { internalName ->
val qualifier = internalName.substringBeforeLast('/', "").replace('/', '.')

View File

@@ -42,7 +42,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -72,7 +71,7 @@ class CoroutineCodegen private constructor(
// protected fun doResume(result, throwable)
private val doResumeDescriptor =
SimpleFunctionDescriptorImpl.create(
classDescriptor, Annotations.EMPTY, Name.identifier("doResume"), CallableMemberDescriptor.Kind.DECLARATION,
classDescriptor, Annotations.EMPTY, Name.identifier(DO_RESUME_METHOD_NAME), CallableMemberDescriptor.Kind.DECLARATION,
funDescriptor.source
).apply doResume@{
initialize(
@@ -289,8 +288,8 @@ class CoroutineCodegen private constructor(
}
private fun allFunctionParameters() =
originalSuspendFunctionDescriptor.extensionReceiverParameter.singletonOrEmptyList() +
originalSuspendFunctionDescriptor.valueParameters.orEmpty()
listOfNotNull(originalSuspendFunctionDescriptor.extensionReceiverParameter) +
originalSuspendFunctionDescriptor.valueParameters.orEmpty()
private fun ParameterDescriptor.getFieldInfoForCoroutineLambdaParameter() =
createHiddenFieldInfo(type, COROUTINE_LAMBDA_PARAMETER_PREFIX + (this.safeAs<ValueParameterDescriptor>()?.index ?: ""))
@@ -328,6 +327,11 @@ class CoroutineCodegen private constructor(
}
companion object {
fun shouldCreateByLambda(
originalSuspendLambdaDescriptor: CallableDescriptor,
declaration: KtElement): Boolean {
return (declaration is KtFunctionLiteral && originalSuspendLambdaDescriptor.isSuspendLambda)
}
@JvmStatic
fun createByLambda(
@@ -336,8 +340,7 @@ class CoroutineCodegen private constructor(
declaration: KtElement,
classBuilder: ClassBuilder
): ClosureCodegen? {
if (declaration !is KtFunctionLiteral) return null
if (!originalSuspendLambdaDescriptor.isSuspendLambda) return null
if (!shouldCreateByLambda(originalSuspendLambdaDescriptor, declaration)) return null
return CoroutineCodegen(
expressionCodegen,

View File

@@ -294,7 +294,7 @@ class CoroutineTransformerMethodVisitor(
get() {
assert(suspensionCallEnd.next is LabelNode) {
"Next instruction after ${this} should be a label, but " +
"${suspensionCallEnd.next.javaClass}/${suspensionCallEnd.next.opcode} was found"
"${suspensionCallEnd.next::class.java}/${suspensionCallEnd.next.opcode} was found"
}
return suspensionCallEnd.next as LabelNode
@@ -421,7 +421,7 @@ private fun InstructionAdapter.generateResumeWithExceptionCheck() {
private fun Type.fieldNameForVar(index: Int) = descriptor.first() + "$" + index
private fun withInstructionAdapter(block: InstructionAdapter.() -> Unit): InsnList {
inline fun withInstructionAdapter(block: InstructionAdapter.() -> Unit): InsnList {
val tmpMethodNode = MethodNode()
InstructionAdapter(tmpMethodNode).apply(block)

View File

@@ -217,7 +217,7 @@ private class VarExpectedTypeFrame(maxLocals: Int) : VarFrame<VarExpectedTypeFra
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
if (other == null || other::class.java != this::class.java) return false
other as VarExpectedTypeFrame

View File

@@ -66,7 +66,6 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
createClassReader().accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
@Override
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, inliningContext.state);
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces);
if(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE.getInternalName().equals(superName)) {
inliningContext.setContinuation(true);
@@ -141,12 +140,12 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
List<CapturedParamInfo> additionalFakeParams =
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder,
transformationInfo, parentRemapper);
List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>();
List<DeferredMethodVisitor> deferringMethods = new ArrayList<DeferredMethodVisitor>();
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, parentRemapper, additionalFakeParams);
for (MethodNode next : methodsToTransform) {
MethodVisitor deferringVisitor = newMethod(classBuilder, next);
DeferredMethodVisitor deferringVisitor = newMethod(classBuilder, next);
InlineResult funResult =
inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false);
@@ -161,7 +160,8 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
deferringMethods.add(deferringVisitor);
}
for (MethodVisitor method : deferringMethods) {
for (DeferredMethodVisitor method : deferringMethods) {
InlineCodegenUtil.removeFinallyMarkers(method.getIntermediate());
method.visitEnd();
}
@@ -270,7 +270,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
//TODO for inline method make public class
transformationInfo.setNewConstructorDescriptor(constructorDescriptor);
MethodVisitor constructorVisitor = classBuilder.newMethod(
NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY
NO_ORIGIN, constructor.access, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY
);
final Label newBodyStartLabel = new Label();
@@ -311,8 +311,9 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
}
MethodNode intermediateMethodNode =
new MethodNode(AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY);
new MethodNode(constructor.access, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY);
inlineMethodAndUpdateGlobalResult(parentRemapper, intermediateMethodNode, constructor, constructorInlineBuilder, true);
InlineCodegenUtil.removeFinallyMarkers(intermediateMethodNode);
AbstractInsnNode first = intermediateMethodNode.instructions.getFirst();
final Label oldStartLabel = first instanceof LabelNode ? ((LabelNode) first).getLabel() : null;

View File

@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
@@ -202,7 +203,7 @@ public class InlineCodegen extends CallGenerator {
MethodNode node = nodeAndSmap != null ? nodeAndSmap.getNode() : null;
throw new CompilationException(
"Couldn't inline method call '" + functionDescriptor.getName() + "' into\n" +
contextDescriptor + "\n" +
DescriptorRenderer.DEBUG_TEXT.render(contextDescriptor) + "\n" +
(element != null ? element.getText() : "<no source>") +
(generateNodeText ? ("\nCause: " + InlineCodegenUtil.getNodeText(node)) : ""),
e, callElement
@@ -321,7 +322,7 @@ public class InlineCodegen extends CallGenerator {
}
});
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId, state);
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId);
}
assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor;
@@ -348,7 +349,7 @@ public class InlineCodegen extends CallGenerator {
});
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId, state);
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId);
}
@NotNull
@@ -466,7 +467,9 @@ public class InlineCodegen extends CallGenerator {
adapter, infos, ((StackValue.Local) remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index
);
removeStaticInitializationTrigger(adapter);
removeFinallyMarkers(adapter);
if (!InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) {
InlineCodegenUtil.removeFinallyMarkers(adapter);
}
adapter.accept(new MethodBodyVisitor(codegen.v));
@@ -1024,25 +1027,6 @@ public class InlineCodegen extends CallGenerator {
//processor.substituteLocalVarTable(intoNode);
}
private void removeFinallyMarkers(@NotNull MethodNode intoNode) {
if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return;
InsnList instructions = intoNode.instructions;
AbstractInsnNode curInstr = instructions.getFirst();
while (curInstr != null) {
if (InlineCodegenUtil.isFinallyMarker(curInstr)) {
AbstractInsnNode marker = curInstr;
//just to assert
getConstant(marker.getPrevious());
curInstr = curInstr.getNext();
instructions.remove(marker.getPrevious());
instructions.remove(marker);
continue;
}
curInstr = curInstr.getNext();
}
}
@NotNull
public static SourceMapper createNestedSourceMapper(@NotNull SMAPAndMethodNode nodeAndSmap, @NotNull SourceMapper parent) {
return new NestedSourceMapper(parent, nodeAndSmap.getSortedRanges(), nodeAndSmap.getClassSMAP().getSourceInfo());

View File

@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.fileClasses.FileClasses;
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder;
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.tree.*;
import org.jetbrains.org.objectweb.asm.util.Printer;
import org.jetbrains.org.objectweb.asm.util.Textifier;
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
@@ -81,7 +82,9 @@ public class InlineCodegenUtil {
private static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall";
private static final String INLINE_MARKER_FINALLY_START = "finallyStart";
private static final String INLINE_MARKER_FINALLY_END = "finallyEnd";
public static final String SPECIAL_TRANSFORMATION_NAME = "$special";
public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined";
public static final String INLINE_CALL_TRANSFORMATION_SUFFIX = "$" + INLINE_TRANSFORMATION_SUFFIX;
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
@@ -90,8 +93,7 @@ public class InlineCodegenUtil {
byte[] classData,
final String methodName,
final String methodDescriptor,
ClassId classId,
final @NotNull GenerationState state
ClassId classId
) {
ClassReader cr = new ClassReader(classData);
final MethodNode[] node = new MethodNode[1];
@@ -101,10 +103,6 @@ public class InlineCodegenUtil {
lines[1] = Integer.MIN_VALUE;
//noinspection PointlessBitwiseExpression
cr.accept(new ClassVisitor(API) {
@Override
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
assertVersionNotGreaterThanGeneratedOne(version, name, state);
}
@Override
public void visitSource(String source, String debug) {
@@ -149,16 +147,6 @@ public class InlineCodegenUtil {
return new SMAPAndMethodNode(node[0], smap);
}
public static void assertVersionNotGreaterThanGeneratedOne(int version, String internalName, @NotNull GenerationState state) {
// TODO: report a proper diagnostic
if (version > state.getClassFileVersion() && !"true".equals(System.getProperty("kotlin.skip.bytecode.version.check"))) {
throw new UnsupportedOperationException(
"Cannot inline bytecode of class " + internalName + " which has version " + version + ". " +
"This compiler can only inline Java 1.6 bytecode (version " + Opcodes.V1_6 + ")"
);
}
}
public static void initDefaultSourceMappingIfNeeded(
@NotNull CodegenContext context, @NotNull MemberCodegen codegen, @NotNull GenerationState state
) {
@@ -177,7 +165,7 @@ public class InlineCodegenUtil {
@Nullable
public static VirtualFile findVirtualFile(@NotNull GenerationState state, @NotNull ClassId classId) {
return JvmVirtualFileFinder.SERVICE.getInstance(state.getProject()).findVirtualFileWithHeader(classId);
return VirtualFileFinder.SERVICE.getInstance(state.getProject()).findVirtualFileWithHeader(classId);
}
@Nullable
@@ -403,6 +391,11 @@ public class InlineCodegenUtil {
return sw.toString().trim();
}
@NotNull
public static String getInsnOpcodeText(@Nullable AbstractInsnNode node) {
return node == null ? "null" : Printer.OPCODES[node.getOpcode()];
}
@NotNull
/* package */ static ClassReader buildClassReaderByInternalName(@NotNull GenerationState state, @NotNull String internalName) {
//try to find just compiled classes then in dependencies
@@ -464,6 +457,23 @@ public class InlineCodegenUtil {
}
}
public static void removeFinallyMarkers(@NotNull MethodNode intoNode) {
InsnList instructions = intoNode.instructions;
AbstractInsnNode curInstr = instructions.getFirst();
while (curInstr != null) {
if (isFinallyMarker(curInstr)) {
AbstractInsnNode marker = curInstr;
//just to assert
getConstant(marker.getPrevious());
curInstr = curInstr.getNext();
instructions.remove(marker.getPrevious());
instructions.remove(marker);
continue;
}
curInstr = curInstr.getNext();
}
}
public static void addInlineMarker(@NotNull InstructionAdapter v, boolean isStartNotEnd) {
v.visitMethodInsn(
Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,

View File

@@ -252,6 +252,7 @@ public class MethodInliner {
//TODO add skipped this and receiver
InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);
result.mergeWithNotChangeInfo(lambdaResult);
result.getReifiedTypeParametersUsages().mergeAll(lambdaResult.getReifiedTypeParametersUsages());
//return value boxing/unboxing
Method bridge = typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor()));
@@ -463,6 +464,7 @@ public class MethodInliner {
Map<Integer, LambdaInfo> lambdaMapping = new HashMap<Integer, LambdaInfo>();
int offset = 0;
boolean capturesAnonymousObjectThatMustBeRegenerated = false;
for (int i = 0; i < paramCount; i++) {
SourceValue sourceValue = frame.getStack(firstParameterIndex + i);
LambdaInfo lambdaInfo = MethodInlinerUtilKt.getLambdaIfExistsAndMarkInstructions(
@@ -471,15 +473,25 @@ public class MethodInliner {
if (lambdaInfo != null) {
lambdaMapping.put(offset, lambdaInfo);
}
else if (i < argTypes.length && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
capturesAnonymousObjectThatMustBeRegenerated = true;
}
offset += i == 0 ? 1 : argTypes[i - 1].getSize();
}
transformations.add(
buildConstructorInvocation(owner, desc, lambdaMapping, awaitClassReification)
buildConstructorInvocation(
owner, desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
)
);
awaitClassReification = false;
}
else if (inliningContext.isInliningLambda && ReifiedTypeInliner.Companion.isOperationReifiedMarker(cur)) {
ReificationArgument reificationArgument = ReifiedTypeInlinerKt.getReificationArgument((MethodInsnNode) cur);
String parameterName = reificationArgument.getParameterName();
result.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterName);
}
}
else if (cur.getOpcode() == Opcodes.GETSTATIC) {
FieldInsnNode fieldInsnNode = (FieldInsnNode) cur;
@@ -538,6 +550,12 @@ public class MethodInliner {
return node;
}
private boolean isAnonymousClassThatMustBeRegenerated(@Nullable Type type) {
if (type == null || type.getSort() != Type.OBJECT) return false;
AnonymousObjectTransformationInfo info = inliningContext.findAnonymousObjectTransformationInfo(type.getInternalName());
return info != null && info.shouldRegenerate(true);
}
@NotNull
private Frame<SourceValue>[] analyzeMethodNodeBeforeInline(@NotNull MethodNode node) {
try {
@@ -584,7 +602,8 @@ public class MethodInliner {
@NotNull String anonymousType,
@NotNull String desc,
@NotNull Map<Integer, LambdaInfo> lambdaMapping,
boolean needReification
boolean needReification,
boolean capturesAnonymousObjectThatMustBeRegenerated
) {
boolean memoizeAnonymousObject = inliningContext.findAnonymousObjectTransformationInfo(anonymousType) == null;
@@ -594,7 +613,8 @@ public class MethodInliner {
isAlreadyRegenerated(anonymousType),
desc,
false,
inliningContext.nameGenerator
inliningContext.nameGenerator,
capturesAnonymousObjectThatMustBeRegenerated
);
if (memoizeAnonymousObject) {

View File

@@ -66,7 +66,6 @@ class WhenMappingTransformer(
val fieldNode = transformationInfo.fieldNode
classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, state)
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
}

View File

@@ -70,7 +70,5 @@ internal class Parameters(val parameters: List<ParameterInfo>) : Iterable<Parame
}
val capturedTypes: List<Type>
get() = captured.map {
it.getType()
}
get() = captured.map(CapturedParamInfo::getType)
}

View File

@@ -70,7 +70,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
const val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker"
const val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification"
private fun isOperationReifiedMarker(insn: AbstractInsnNode) =
fun isOperationReifiedMarker(insn: AbstractInsnNode) =
isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME }
private fun isReifiedMarker(insn: AbstractInsnNode, namePredicate: (String) -> Boolean): Boolean {
@@ -247,7 +247,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
}
}
private val MethodInsnNode.reificationArgument: ReificationArgument?
val MethodInsnNode.reificationArgument: ReificationArgument?
get() {
val prev = previous!!

View File

@@ -57,7 +57,7 @@ class SMAPBuilder(
private fun generateDebugStrata(realMappings: List<FileMapping>): String {
val combinedMapping = FileMapping(source, path)
realMappings.forEach { fileMapping ->
fileMapping.lineMappings.filter { it.callSiteMarker != null }.forEach { (source, dest, range, callSiteMarker) ->
fileMapping.lineMappings.filter { it.callSiteMarker != null }.forEach { (_, dest, range, callSiteMarker) ->
combinedMapping.addRangeMapping(RangeMapping(
callSiteMarker!!.lineNumber, dest, range
))

View File

@@ -68,7 +68,8 @@ class AnonymousObjectTransformationInfo internal constructor(
private val alreadyRegenerated: Boolean,
val constructorDesc: String?,
private val isStaticOrigin: Boolean,
parentNameGenerator: NameGenerator
parentNameGenerator: NameGenerator,
private val capturesAnonymousObjectThatMustBeRegenerated: Boolean = false
) : TransformationInfo {
override val nameGenerator by lazy {
@@ -93,7 +94,8 @@ class AnonymousObjectTransformationInfo internal constructor(
) : this(ownerInternalName, needReification, hashMapOf(), false, alreadyRegenerated, null, isStaticOrigin, nameGenerator)
override fun shouldRegenerate(sameModule: Boolean): Boolean =
!alreadyRegenerated && (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification)
!alreadyRegenerated &&
(!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated)
override fun canRemoveAfterTransformation(): Boolean {
// Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda

View File

@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class CompareTo : IntrinsicMethod() {
private fun genInvoke(type: Type?, v: InstructionAdapter) {
when (type) {
Type.INT_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
Type.INT_TYPE, Type.CHAR_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
Type.LONG_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
Type.FLOAT_TYPE -> v.invokestatic("java/lang/Float", "compare", "(FF)I", false)
Type.DOUBLE_TYPE -> v.invokestatic("java/lang/Double", "compare", "(DD)I", false)

View File

@@ -47,12 +47,12 @@ class Concat : IntrinsicMethod() {
codegen.invokeAppend(element.right)
}
else {
// LHS?.plus(RHS)
receiver.put(AsmTypes.OBJECT_TYPE, v)
// Explicit plus call LHS?.plus(RHS) or LHS.plus(RHS)
receiver.put(AsmTypes.JAVA_STRING_TYPE, v)
genStringBuilderConstructor(v)
v.swap()
genInvokeAppendMethod(v, returnType)
codegen.invokeAppend(arguments.get(0))
codegen.invokeAppend(arguments[0])
}
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)

View File

@@ -28,7 +28,7 @@ internal val classId: ClassId =
ClassId.topLevel(FqName("org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt"))
internal val bytecode: ByteArray by lazy {
val stream = object {}.javaClass.classLoader.getResourceAsStream("${classId.asString()}.class")
val stream = object {}::class.java.classLoader.getResourceAsStream("${classId.asString()}.class")
stream.readBytes().apply {
stream.close()
}

View File

@@ -58,7 +58,7 @@ object JavaClassProperty : IntrinsicPropertyGetter() {
}
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
val classType = codegen.getState().typeMapper.mapType(resolvedCall.call.dispatchReceiver!!.type)
val classType = codegen.state.typeMapper.mapType(resolvedCall.call.dispatchReceiver!!.type)
return object : IntrinsicCallable(getType(Class::class.java), listOf(), classType, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
if (isPrimitive(classType)) {

View File

@@ -26,7 +26,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class NewArray : IntrinsicMethod() {
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
val jetType = resolvedCall.resultingDescriptor.returnType!!
val type = codegen.getState().typeMapper.mapType(jetType)
val type = codegen.state.typeMapper.mapType(jetType)
return object : IntrinsicCallable(type, listOf(Type.INT_TYPE), null, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
codegen.newArrayInstruction(jetType)

View File

@@ -29,9 +29,13 @@ class DeadCodeEliminationMethodTransformer : MethodTransformer() {
}
fun transformWithResult(internalClassName: String, methodNode: MethodNode): Result {
val frames = analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
return removeDeadCodeByFrames(methodNode, frames)
}
fun removeDeadCodeByFrames(methodNode: MethodNode, frames: Array<out Any?>): Result {
val removedNodes = HashSet<AbstractInsnNode>()
val frames = analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
val insnList = methodNode.instructions
val insnsArray = insnList.toArray()
@@ -51,6 +55,7 @@ class DeadCodeEliminationMethodTransformer : MethodTransformer() {
}
class Result(val removedNodes: Set<AbstractInsnNode>) {
fun hasRemovedAnything() = removedNodes.isNotEmpty()
fun isRemoved(node: AbstractInsnNode) = removedNodes.contains(node)
fun isAlive(node: AbstractInsnNode) = !isRemoved(node)
}

View File

@@ -21,8 +21,9 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor;
import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantBoxingMethodTransformer;
import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantCoercionToUnitTransformer;
import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantNullCheckMethodTransformer;
import org.jetbrains.kotlin.codegen.optimization.captured.CapturedVarsOptimizationMethodTransformer;
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
import org.jetbrains.kotlin.codegen.optimization.nullCheck.RedundantNullCheckV2MethodTransformer;
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
@@ -33,7 +34,9 @@ public class OptimizationMethodVisitor extends TransformationMethodVisitor {
private static final MethodTransformer MANDATORY_METHOD_TRANSFORMER = new FixStackWithLabelNormalizationMethodTransformer();
private static final MethodTransformer[] OPTIMIZATION_TRANSFORMERS = new MethodTransformer[] {
new RedundantNullCheckMethodTransformer(),
new CapturedVarsOptimizationMethodTransformer(),
new RedundantNullCheckV2MethodTransformer(),
new RedundantCheckCastEliminationMethodTransformer(),
new RedundantBoxingMethodTransformer(),
new RedundantCoercionToUnitTransformer(),
new DeadCodeEliminationMethodTransformer(),

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.nullCheck.popReferenceValueBefore
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
class RedundantCheckCastEliminationMethodTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
val insns = methodNode.instructions.toArray()
if (!insns.any { it.opcode == Opcodes.CHECKCAST }) return
val redundantCheckCasts = ArrayList<TypeInsnNode>()
val frames = analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
for (i in insns.indices) {
val valueType = frames[i]?.top()?.type ?: continue
val insn = insns[i]
if (ReifiedTypeInliner.isOperationReifiedMarker(insn.previous)) continue
if (insn is TypeInsnNode) {
val insnType = Type.getObjectType(insn.desc)
if (!isTrivialSubtype(insnType, valueType)) continue
if (insn.opcode == Opcodes.CHECKCAST) {
redundantCheckCasts.add(insn)
}
}
}
redundantCheckCasts.forEach {
methodNode.instructions.remove(it)
}
}
private fun isTrivialSubtype(superType: Type, subType: Type) =
superType == subType
}

View File

@@ -20,7 +20,6 @@ import com.intellij.openapi.util.Pair
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.toReadOnlyList
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import java.util.*
@@ -66,7 +65,7 @@ class BoxedValueDescriptor(
var isSafeToRemove = true; private set
val unboxedType: Type = getUnboxedType(boxedType)
fun getAssociatedInsns() = associatedInsns.toReadOnlyList()
fun getAssociatedInsns() = associatedInsns.toList()
fun addInsn(insnNode: AbstractInsnNode) {
associatedInsns.add(insnNode)

View File

@@ -35,14 +35,12 @@ import java.util.*
open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasicInterpreter() {
private val boxingPlaces = HashMap<Int, BoxedBasicValue>()
protected open fun createNewBoxing(insn: AbstractInsnNode, type: Type, progressionIterator: ProgressionIteratorBasicValue?): BasicValue {
val index = insnList.indexOf(insn)
return boxingPlaces.getOrPut(index) {
val boxedBasicValue = CleanBoxedValue(type, insn, progressionIterator)
onNewBoxedValue(boxedBasicValue)
boxedBasicValue
}
}
protected open fun createNewBoxing(insn: AbstractInsnNode, type: Type, progressionIterator: ProgressionIteratorBasicValue?): BasicValue =
boxingPlaces.getOrPut(insnList.indexOf(insn)) {
val boxedBasicValue = CleanBoxedValue(type, insn, progressionIterator)
onNewBoxedValue(boxedBasicValue)
boxedBasicValue
}
protected fun checkUsedValue(value: BasicValue) {
if (value is TaintedBoxedValue) {
@@ -66,14 +64,17 @@ open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasic
onUnboxing(insn, firstArg, value.type)
value
}
insn.isIteratorMethodCallOfProgression(values) -> {
ProgressionIteratorBasicValue(getValuesTypeOfProgressionClass(firstArg.type.internalName))
}
insn.isIteratorMethodCallOfProgression(values) ->
ProgressionIteratorBasicValue.byProgressionClassType(firstArg.type)
insn.isNextMethodCallOfProgressionIterator(values) -> {
val progressionIterator = firstArg as? ProgressionIteratorBasicValue
?: throw AssertionError("firstArg should be progression iterator")
createNewBoxing(insn, AsmUtil.boxType(progressionIterator.valuesPrimitiveType), progressionIterator)
}
insn.isAreEqualIntrinsicForSameTypedBoxedValues(values) && canValuesBeUnboxedForAreEqual(values) -> {
onAreEqual(insn, values[0] as BoxedBasicValue, values[1] as BoxedBasicValue)
value
}
else -> {
// N-ary operation should be a method call or multinewarray.
// Arguments for multinewarray could be only numeric,
@@ -100,7 +101,7 @@ open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasic
protected open fun isExactValue(value: BasicValue) =
value is ProgressionIteratorBasicValue ||
value is CleanBoxedValue ||
value.type != null && isProgressionClass(value.type.internalName)
value.type != null && isProgressionClass(value.type)
override fun merge(v: BasicValue, w: BasicValue) =
when {
@@ -125,6 +126,7 @@ open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasic
protected open fun onNewBoxedValue(value: BoxedBasicValue) {}
protected open fun onUnboxing(insn: AbstractInsnNode, value: BoxedBasicValue, resultType: Type) {}
protected open fun onAreEqual(insn: AbstractInsnNode, value1: BoxedBasicValue, value2: BoxedBasicValue) {}
protected open fun onMethodCallWithBoxedValue(value: BoxedBasicValue) {}
protected open fun onMergeFail(value: BoxedBasicValue) {}
protected open fun onMergeSuccess(v: BoxedBasicValue, w: BoxedBasicValue) {}
@@ -190,23 +192,44 @@ private fun AbstractInsnNode.isJavaLangClassBoxing() =
desc == JLCLASS_TO_KCLASS
}
private fun AbstractInsnNode.isNextMethodCallOfProgressionIterator(values: List<BasicValue>) =
values[0] is ProgressionIteratorBasicValue &&
fun AbstractInsnNode.isNextMethodCallOfProgressionIterator(values: List<BasicValue>) =
values.firstOrNull() is ProgressionIteratorBasicValue &&
isMethodInsnWith(Opcodes.INVOKEINTERFACE) {
name == "next"
}
private fun AbstractInsnNode.isIteratorMethodCallOfProgression(values: List<BasicValue>) =
fun AbstractInsnNode.isIteratorMethodCallOfProgression(values: List<BasicValue>) =
isMethodInsnWith(Opcodes.INVOKEINTERFACE) {
val firstArgType = values[0].type
val firstArgType = values.firstOrNull()?.type
firstArgType != null &&
isProgressionClass(firstArgType.internalName) &&
isProgressionClass(firstArgType) &&
name == "iterator"
}
private fun isProgressionClass(internalClassName: String) =
RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(internalClassName))
fun isProgressionClass(type: Type) =
RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(type.internalName))
private fun getValuesTypeOfProgressionClass(progressionClassInternalName: String) =
RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(buildFqNameByInternal(progressionClassInternalName))
?.typeName?.asString() ?: error("type should be not null")
fun AbstractInsnNode.isAreEqualIntrinsicForSameTypedBoxedValues(values: List<BasicValue>) =
isAreEqualIntrinsic() && run {
if (values.size != 2) return false
val (v1, v2) = values
if (v1 !is BoxedBasicValue || v2 !is BoxedBasicValue) return false
val d1 = v1.descriptor
val d2 = v2.descriptor
d1.unboxedType == d2.unboxedType
}
fun AbstractInsnNode.isAreEqualIntrinsic() =
isMethodInsnWith(Opcodes.INVOKESTATIC) {
name == "areEqual" &&
owner == "kotlin/jvm/internal/Intrinsics" &&
desc == "(Ljava/lang/Object;Ljava/lang/Object;)Z"
}
fun canValuesBeUnboxedForAreEqual(values: List<BasicValue>): Boolean =
!values.any {
val unboxedType = getUnboxedType(it.type)
unboxedType == Type.DOUBLE_TYPE || unboxedType == Type.FLOAT_TYPE
}

View File

@@ -1,53 +0,0 @@
/*
* Copyright 2010-2014 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.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
class NullabilityInterpreter(insns: InsnList) : BoxingInterpreter(insns) {
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue) = makeNotNullIfNeeded(insn, super.unaryOperation(insn, value))
override fun newOperation(insn: AbstractInsnNode) = makeNotNullIfNeeded(insn, super.newOperation(insn))
override fun isExactValue(value: BasicValue) = super.isExactValue(value) || value is NotNullBasicValue
override fun createNewBoxing(insn: AbstractInsnNode, type: Type, progressionIterator: ProgressionIteratorBasicValue?) =
NotNullBasicValue(type)
}
private fun makeNotNullIfNeeded(insn: AbstractInsnNode, value: BasicValue?): BasicValue? =
when (insn.opcode) {
Opcodes.ANEWARRAY, Opcodes.NEWARRAY, Opcodes.LDC, Opcodes.NEW ->
if (value?.type?.sort == Type.OBJECT || value?.type?.sort == Type.ARRAY)
NotNullBasicValue(value.type)
else
value
else -> value
}
class NotNullBasicValue(type: Type?) : StrictBasicValue(type) {
override fun equals(other: Any?): Boolean = other is NotNullBasicValue
// We do not differ not-nullable values, so we should always return the same hashCode
// Actually it doesn't really matter because analyzer is not supposed to store values in hashtables
override fun hashCode() = 0
}

View File

@@ -18,17 +18,18 @@ package org.jetbrains.kotlin.codegen.optimization.boxing;
import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.codegen.RangeCodegenUtil;
import org.jetbrains.kotlin.codegen.intrinsics.IteratorNext;
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
import org.jetbrains.org.objectweb.asm.Type;
public class ProgressionIteratorBasicValue extends StrictBasicValue {
private final static ImmutableMap<String, Type> VALUES_TYPENAME_TO_TYPE;
static {
ImmutableMap.Builder<String, Type> builder = ImmutableMap.builder();
for (PrimitiveType primitiveType : RangeCodegenUtil.supportedRangeTypes()) {
@@ -37,6 +38,15 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
VALUES_TYPENAME_TO_TYPE = builder.build();
}
private static final ImmutableMap<PrimitiveType, ProgressionIteratorBasicValue> ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE;
static {
ImmutableMap.Builder<PrimitiveType, ProgressionIteratorBasicValue> builder = ImmutableMap.builder();
for (PrimitiveType elementType : RangeCodegenUtil.supportedRangeTypes()) {
builder.put(elementType, new ProgressionIteratorBasicValue(elementType.getTypeName().asString()));
}
ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE = builder.build();
}
@NotNull
private static Type getValuesType(@NotNull String valuesTypeName) {
Type type = VALUES_TYPENAME_TO_TYPE.get(valuesTypeName);
@@ -47,12 +57,20 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
private final Type valuesPrimitiveType;
private final String valuesPrimitiveTypeName;
public ProgressionIteratorBasicValue(@NotNull String valuesPrimitiveTypeName) {
private ProgressionIteratorBasicValue(@NotNull String valuesPrimitiveTypeName) {
super(IteratorNext.Companion.getPrimitiveIteratorType(Name.identifier(valuesPrimitiveTypeName)));
this.valuesPrimitiveType = getValuesType(valuesPrimitiveTypeName);
this.valuesPrimitiveTypeName = valuesPrimitiveTypeName;
}
@Nullable
public static ProgressionIteratorBasicValue byProgressionClassType(@NotNull Type progressionClassType) {
FqName classFqName = new FqName(progressionClassType.getClassName());
PrimitiveType elementType = RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(classFqName);
return ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE.get(elementType);
}
@NotNull
public Type getValuesPrimitiveType() {
return valuesPrimitiveType;

View File

@@ -84,6 +84,13 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
}
}
override fun onAreEqual(insn: AbstractInsnNode, value1: BoxedBasicValue, value2: BoxedBasicValue) {
val descriptor1 = value1.descriptor
val descriptor2 = value2.descriptor
candidatesBoxedValues.merge(descriptor1, descriptor2)
descriptor1.addInsn(insn)
}
override fun onMethodCallWithBoxedValue(value: BoxedBasicValue) {
markValueAsDirty(value)
}

View File

@@ -21,7 +21,9 @@ import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue;
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
@@ -48,7 +50,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
adaptLocalVariableTableForBoxedValues(node, frames);
applyVariablesRemapping(node, buildVariablesRemapping(valuesToOptimize, node));
UtilKt.remapLocalVariables(node, buildVariablesRemapping(valuesToOptimize, node));
adaptInstructionsForBoxedValues(node, valuesToOptimize);
}
@@ -221,21 +223,6 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
return remapping;
}
private static void applyVariablesRemapping(@NotNull MethodNode node, @NotNull int[] remapping) {
for (AbstractInsnNode insn : node.instructions.toArray()) {
if (insn instanceof VarInsnNode) {
((VarInsnNode) insn).var = remapping[((VarInsnNode) insn).var];
}
if (insn instanceof IincInsnNode) {
((IincInsnNode) insn).var = remapping[((IincInsnNode) insn).var];
}
}
for (LocalVariableNode localVariableNode : node.localVariables) {
localVariableNode.index = remapping[localVariableNode.index];
}
}
private static void adaptInstructionsForBoxedValues(
@NotNull MethodNode node,
@NotNull RedundantBoxedValuesCollection values
@@ -341,9 +328,68 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
);
node.instructions.set(insn, new InsnNode(Opcodes.ICONST_1));
break;
case Opcodes.INVOKESTATIC:
if (BoxingInterpreterKt.isAreEqualIntrinsic(insn)) {
adaptAreEqualIntrinsic(node, insn, value);
break;
}
else {
// fall-through to default
}
default:
// CHECKCAST or unboxing-method call
node.instructions.remove(insn);
}
}
private static void adaptAreEqualIntrinsic(@NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedValueDescriptor value) {
Type unboxedType = value.getUnboxedType();
switch (unboxedType.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
case Type.CHAR:
adaptAreEqualIntrinsicForInt(node, insn);
break;
case Type.LONG:
adaptAreEqualIntrinsicForLong(node, insn);
break;
case Type.OBJECT:
break;
default:
throw new AssertionError("Unexpected unboxed type kind: " + unboxedType);
}
}
private static void adaptAreEqualIntrinsicForInt(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
LabelNode lNotEqual = new LabelNode(new Label());
LabelNode lDone = new LabelNode(new Label());
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.IF_ICMPNE, lNotEqual));
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_1));
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.GOTO, lDone));
node.instructions.insertBefore(insn, lNotEqual);
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_0));
node.instructions.insertBefore(insn, lDone);
node.instructions.remove(insn);
}
private static void adaptAreEqualIntrinsicForLong(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
node.instructions.insertBefore(insn, new InsnNode(Opcodes.LCMP));
ifEqual1Else0(node, insn);
node.instructions.remove(insn);
}
private static void ifEqual1Else0(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
LabelNode lNotEqual = new LabelNode(new Label());
LabelNode lDone = new LabelNode(new Label());
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.IFNE, lNotEqual));
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_1));
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.GOTO, lDone));
node.instructions.insertBefore(insn, lNotEqual);
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_0));
node.instructions.insertBefore(insn, lDone);
}
}

View File

@@ -63,7 +63,7 @@ class RedundantCoercionToUnitTransformer : MethodTransformer() {
private val frames by lazy { analyzeMethodBody() }
fun transform() {
if (!insns.any { it.isUnitOrNull() }) return
if (!insns.any { it.isUnitInstanceOrNull() }) return
computeTransformations()
for ((insn, transformation) in transformations.entries) {
@@ -158,7 +158,7 @@ class RedundantCoercionToUnitTransformer : MethodTransformer() {
transformations[insn] = replaceWithPopTransformation(boxedValueSize)
}
insn.isUnitOrNull() -> {
insn.isUnitInstanceOrNull() -> {
transformations[insn] = replaceWithNopTransformation()
}
@@ -232,7 +232,7 @@ class RedundantCoercionToUnitTransformer : MethodTransformer() {
it.isPrimitiveBoxing() && (it as MethodInsnNode).owner == resultType
private fun isTransformablePopOperand(insn: AbstractInsnNode) =
insn.opcode == Opcodes.CHECKCAST || insn.isPrimitiveBoxing() || insn.isUnitOrNull()
insn.opcode == Opcodes.CHECKCAST || insn.isPrimitiveBoxing() || insn.isUnitInstanceOrNull()
private fun isDontTouch(insn: AbstractInsnNode) =
dontTouchInsnIndices[insnList.indexOf(insn)]
@@ -240,6 +240,9 @@ class RedundantCoercionToUnitTransformer : MethodTransformer() {
}
fun AbstractInsnNode.isUnitOrNull() =
opcode == Opcodes.ACONST_NULL ||
opcode == Opcodes.GETSTATIC && this is FieldInsnNode && owner == "kotlin/Unit" && name == "INSTANCE"
fun AbstractInsnNode.isUnitInstanceOrNull() =
opcode == Opcodes.ACONST_NULL || isUnitInstance()
fun AbstractInsnNode.isUnitInstance() =
opcode == Opcodes.GETSTATIC &&
this is FieldInsnNode && owner == "kotlin/Unit" && name == "INSTANCE"

View File

@@ -1,81 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.boxing;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.tree.*;
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame;
import java.util.ArrayList;
import java.util.List;
public class RedundantNullCheckMethodTransformer extends MethodTransformer {
@Override
public void transform(@NotNull String internalClassName, @NotNull MethodNode methodNode) {
while (removeRedundantNullCheckPass(internalClassName, methodNode)) {
//do nothing
}
}
private static boolean removeRedundantNullCheckPass(@NotNull String internalClassName, @NotNull MethodNode methodNode) {
InsnList insnList = methodNode.instructions;
Frame<BasicValue>[] frames = analyze(
internalClassName, methodNode,
new NullabilityInterpreter(insnList)
);
List<AbstractInsnNode> insnsToOptimize = new ArrayList<AbstractInsnNode>();
for (int i = 0; i < insnList.size(); i++) {
Frame<BasicValue> frame = frames[i];
AbstractInsnNode insn = insnList.get(i);
if ((insn.getOpcode() == Opcodes.IFNULL || insn.getOpcode() == Opcodes.IFNONNULL) &&
frame != null && frame.getStack(frame.getStackSize() - 1) instanceof NotNullBasicValue) {
insnsToOptimize.add(insn);
}
}
for (AbstractInsnNode insn : insnsToOptimize) {
if (insn.getPrevious() != null && insn.getPrevious().getOpcode() == Opcodes.DUP) {
insnList.remove(insn.getPrevious());
}
else {
insnList.insertBefore(insn, new InsnNode(Opcodes.POP));
}
assert insn.getOpcode() == Opcodes.IFNULL
|| insn.getOpcode() == Opcodes.IFNONNULL : "only IFNULL/IFNONNULL are supported";
if (insn.getOpcode() == Opcodes.IFNULL) {
insnList.remove(insn);
}
else {
insnList.set(
insn,
new JumpInsnNode(Opcodes.GOTO, ((JumpInsnNode) insn).label)
);
}
}
return insnsToOptimize.size() > 0;
}
}

View File

@@ -0,0 +1,264 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.captured
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.codegen.optimization.common.removeEmptyCatchBlocks
import org.jetbrains.kotlin.codegen.optimization.common.removeUnusedLocalVariables
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
Transformer(internalClassName, methodNode).run()
}
// Tracks proper usages of objects corresponding to captured variables.
//
// The 'kotlin.jvm.internal.Ref.*' instance can be replaced with a local variable,
// if all of the following conditions are satisfied:
// * It is created inside a current method.
// * The only permitted operations on it are:
// - store to a local variable
// - ALOAD, ASTORE
// - DUP, POP
// - GETFIELD <owner>.element, PUTFIELD <owner>.element
// * There's a corresponding local variable definition,
// and all ALOAD/ASTORE instructions operate on that particular local variable.
// * Its 'element' field is initialized at start of local variable visibility range.
//
// Note that for code that doesn't create Ref objects explicitly these conditions are true,
// unless the Ref object escapes to a local class constructor (including local classes for lambdas).
//
private class CapturedVarDescriptor(val newInsn: TypeInsnNode, val refType: Type, val valueType: Type) : ReferenceValueDescriptor {
var hazard = false
var initCallInsn: MethodInsnNode? = null
var localVar: LocalVariableNode? = null
var localVarIndex = -1
val astoreInsns: MutableCollection<VarInsnNode> = LinkedHashSet()
val aloadInsns: MutableCollection<VarInsnNode> = LinkedHashSet()
val stackInsns: MutableCollection<AbstractInsnNode> = LinkedHashSet()
val getFieldInsns: MutableCollection<FieldInsnNode> = LinkedHashSet()
val putFieldInsns: MutableCollection<FieldInsnNode> = LinkedHashSet()
fun canRewrite(): Boolean =
!hazard &&
initCallInsn != null &&
localVar != null &&
localVarIndex >= 0
override fun onUseAsTainted() {
hazard = true
}
}
private class Transformer(private val internalClassName: String, private val methodNode: MethodNode) {
private val refValues = ArrayList<CapturedVarDescriptor>()
private val refValuesByNewInsn = LinkedHashMap<TypeInsnNode, CapturedVarDescriptor>()
private val insns = methodNode.instructions.toArray()
private lateinit var frames: Array<out Frame<BasicValue>?>
val hasRewritableRefValues: Boolean
get() = refValues.isNotEmpty()
fun run() {
createRefValues()
if (!hasRewritableRefValues) return
analyze()
if (!hasRewritableRefValues) return
rewrite()
}
private fun AbstractInsnNode.getIndex() = methodNode.instructions.indexOf(this)
private fun createRefValues() {
for (insn in insns) {
if (insn.opcode == Opcodes.NEW && insn is TypeInsnNode) {
val type = Type.getObjectType(insn.desc)
if (AsmTypes.isSharedVarType(type)) {
val valueType = REF_TYPE_TO_ELEMENT_TYPE[type.internalName] ?: continue
val refValue = CapturedVarDescriptor(insn, type, valueType)
refValues.add(refValue)
refValuesByNewInsn[insn] = refValue
}
}
}
}
private inner class Interpreter : ReferenceTrackingInterpreter() {
override fun newOperation(insn: AbstractInsnNode): BasicValue =
refValuesByNewInsn[insn]?.let { descriptor ->
ProperTrackedReferenceValue(descriptor.refType, descriptor)
}
?: super.newOperation(insn)
override fun processRefValueUsage(value: TrackedReferenceValue, insn: AbstractInsnNode, position: Int) {
for (descriptor in value.descriptors) {
if (descriptor !is CapturedVarDescriptor) throw AssertionError("Unexpected descriptor: $descriptor")
when {
insn.opcode == Opcodes.ALOAD ->
descriptor.aloadInsns.add(insn as VarInsnNode)
insn.opcode == Opcodes.ASTORE ->
descriptor.astoreInsns.add(insn as VarInsnNode)
insn.opcode == Opcodes.GETFIELD && insn is FieldInsnNode && insn.name == REF_ELEMENT_FIELD && position == 0 ->
descriptor.getFieldInsns.add(insn)
insn.opcode == Opcodes.PUTFIELD && insn is FieldInsnNode && insn.name == REF_ELEMENT_FIELD && position == 0 ->
descriptor.putFieldInsns.add(insn)
insn.opcode == Opcodes.INVOKESPECIAL && insn is MethodInsnNode && insn.name == INIT_METHOD_NAME && position == 0 ->
if (descriptor.initCallInsn != null && descriptor.initCallInsn != insn)
descriptor.hazard = true
else
descriptor.initCallInsn = insn
insn.opcode == Opcodes.DUP ->
descriptor.stackInsns.add(insn)
else ->
descriptor.hazard = true
}
}
}
}
private fun analyze() {
frames = MethodTransformer.analyze(internalClassName, methodNode, Interpreter())
trackPops()
assignLocalVars()
refValues.removeAll { !it.canRewrite() }
}
private fun trackPops() {
for (i in insns.indices) {
val frame = frames[i] ?: continue
val insn = insns[i]
when (insn.opcode) {
Opcodes.POP -> {
frame.top()?.getCapturedVarOrNull()?.run { stackInsns.add(insn) }
}
Opcodes.POP2 -> {
val top = frame.top()
if (top?.size == 1) {
top.getCapturedVarOrNull()?.hazard = true
frame.peek(1)?.getCapturedVarOrNull()?.hazard = true
}
}
}
}
}
private fun BasicValue.getCapturedVarOrNull() =
safeAs<ProperTrackedReferenceValue>()?.descriptor?.safeAs<CapturedVarDescriptor>()
private fun assignLocalVars() {
for (localVar in methodNode.localVariables) {
val type = Type.getType(localVar.desc)
if (!AsmTypes.isSharedVarType(type)) continue
val startFrame = frames[localVar.start.getIndex()] ?: continue
val refValue = startFrame.getLocal(localVar.index) as? ProperTrackedReferenceValue ?: continue
val descriptor = refValue.descriptor as? CapturedVarDescriptor ?: continue
if (descriptor.hazard) continue
if (descriptor.localVar == null) {
descriptor.localVar = localVar
}
else {
descriptor.hazard = true
}
}
for (refValue in refValues) {
if (refValue.hazard) continue
val localVar = refValue.localVar ?: continue
if (refValue.valueType.size != 1) {
refValue.localVarIndex = methodNode.maxLocals
methodNode.maxLocals += 2
localVar.index = refValue.localVarIndex
}
else {
refValue.localVarIndex = localVar.index
}
val startIndex = localVar.start.getIndex()
val initFieldInsns = refValue.putFieldInsns.filter { it.getIndex() < startIndex }
if (initFieldInsns.size != 1) {
refValue.hazard = true
continue
}
}
}
private fun rewrite() {
for (refValue in refValues) {
if (!refValue.canRewrite()) continue
rewriteRefValue(refValue)
}
methodNode.removeEmptyCatchBlocks()
methodNode.removeUnusedLocalVariables()
}
private fun rewriteRefValue(capturedVar: CapturedVarDescriptor) {
methodNode.instructions.run {
capturedVar.localVar!!.let {
it.signature = null
it.desc = capturedVar.valueType.descriptor
}
remove(capturedVar.newInsn)
remove(capturedVar.initCallInsn!!)
capturedVar.stackInsns.forEach { remove(it) }
capturedVar.aloadInsns.forEach { remove(it) }
capturedVar.astoreInsns.forEach { remove(it) }
capturedVar.getFieldInsns.forEach {
set(it, VarInsnNode(capturedVar.valueType.getOpcode(Opcodes.ILOAD), capturedVar.localVarIndex))
}
capturedVar.putFieldInsns.forEach {
set(it, VarInsnNode(capturedVar.valueType.getOpcode(Opcodes.ISTORE), capturedVar.localVarIndex))
}
}
}
}
}
internal const val REF_ELEMENT_FIELD = "element"
internal const val INIT_METHOD_NAME = "<init>"
internal val REF_TYPE_TO_ELEMENT_TYPE = HashMap<String, Type>().apply {
put(AsmTypes.OBJECT_REF_TYPE.internalName, AsmTypes.OBJECT_TYPE)
PrimitiveType.values().forEach {
put(AsmTypes.sharedTypeForPrimitive(it).internalName, AsmTypes.valueTypeForPrimitive(it))
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.captured
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
abstract class ReferenceTrackingInterpreter : OptimizationBasicInterpreter() {
override fun merge(v: BasicValue, w: BasicValue): BasicValue =
when {
v is ProperTrackedReferenceValue && w is ProperTrackedReferenceValue ->
if (v.descriptor == w.descriptor)
v
else
TaintedTrackedReferenceValue(
getTaintedValueType(v.type, w.type),
setOf(v.descriptor, w.descriptor)
)
v is TrackedReferenceValue || w is TrackedReferenceValue ->
TaintedTrackedReferenceValue(
getTaintedValueType(v.type, w.type),
v.referenceValueDescriptors + w.referenceValueDescriptors
)
else ->
super.merge(v, w)
}
private val BasicValue.referenceValueDescriptors: Set<ReferenceValueDescriptor>
get() = if (this is TrackedReferenceValue) this.descriptors else emptySet()
private fun getTaintedValueType(type1: Type?, type2: Type?): Type =
when {
type1 == null || type2 == null -> AsmTypes.OBJECT_TYPE
type1 == type2 -> type1
else -> AsmTypes.OBJECT_TYPE
}
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue? =
if (value is TrackedReferenceValue) {
checkRefValuesUsages(insn, listOf(value))
value
}
else {
super.copyOperation(insn, value)
}
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue? {
checkRefValuesUsages(insn, listOf(value))
return super.unaryOperation(insn, value)
}
override fun binaryOperation(insn: AbstractInsnNode, value1: BasicValue, value2: BasicValue): BasicValue? {
checkRefValuesUsages(insn, listOf(value1, value2))
return super.binaryOperation(insn, value1, value2)
}
override fun ternaryOperation(insn: AbstractInsnNode, value1: BasicValue, value2: BasicValue, value3: BasicValue): BasicValue? {
checkRefValuesUsages(insn, listOf(value1, value2, value3))
return super.ternaryOperation(insn, value1, value2, value3)
}
override fun naryOperation(insn: AbstractInsnNode, values: List<BasicValue>): BasicValue? {
checkRefValuesUsages(insn, values)
return super.naryOperation(insn, values)
}
protected open fun checkRefValuesUsages(insn: AbstractInsnNode, values: List<BasicValue>) {
values.forEach { value ->
if (value is TaintedTrackedReferenceValue) {
value.descriptors.forEach { it.onUseAsTainted() }
}
}
values.forEachIndexed { pos, value ->
if (value is TrackedReferenceValue) {
processRefValueUsage(value, insn, pos)
}
}
}
protected abstract fun processRefValueUsage(value: TrackedReferenceValue, insn: AbstractInsnNode, position: Int)
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.captured
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.org.objectweb.asm.Type
interface ReferenceValueDescriptor {
fun onUseAsTainted()
}
abstract class TrackedReferenceValue(type: Type): StrictBasicValue(type) {
abstract val descriptors: Set<ReferenceValueDescriptor>
}
class ProperTrackedReferenceValue(type: Type, val descriptor: ReferenceValueDescriptor) : TrackedReferenceValue(type) {
override val descriptors: Set<ReferenceValueDescriptor>
get() = setOf(descriptor)
override fun equals(other: Any?): Boolean =
other === this ||
other is ProperTrackedReferenceValue && other.descriptor == this.descriptor
override fun hashCode(): Int =
descriptor.hashCode()
override fun toString(): String =
"[$descriptor]"
}
class TaintedTrackedReferenceValue(type: Type, override val descriptors: Set<ReferenceValueDescriptor>) : TrackedReferenceValue(type) {
override fun equals(other: Any?): Boolean =
other === this ||
other is TaintedTrackedReferenceValue && other.descriptors == this.descriptors
override fun hashCode(): Int =
descriptors.hashCode()
override fun toString(): String =
"!$descriptors"
}

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.optimization.common;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.AsmUtil;
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
import org.jetbrains.org.objectweb.asm.Handle;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
@@ -136,7 +137,7 @@ public class OptimizationBasicInterpreter extends Interpreter<BasicValue> implem
case NEW:
return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
default:
throw new Error("Internal error.");
throw new IllegalArgumentException("Unexpected instruction: " + InlineCodegenUtil.getInsnOpcodeText(insn));
}
}
@@ -221,7 +222,7 @@ public class OptimizationBasicInterpreter extends Interpreter<BasicValue> implem
case PUTFIELD:
return null;
default:
throw new Error("Internal error.");
throw new IllegalArgumentException("Unexpected instruction: " + InlineCodegenUtil.getInsnOpcodeText(insn));
}
}
@@ -340,7 +341,7 @@ public class OptimizationBasicInterpreter extends Interpreter<BasicValue> implem
case IFNONNULL:
return null;
default:
throw new Error("Internal error.");
throw new IllegalArgumentException("Unexpected instruction: " + InlineCodegenUtil.getInsnOpcodeText(insn));
}
}

View File

@@ -52,7 +52,7 @@ open class StrictBasicValue(type: Type?) : BasicValue(type) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
if (other == null || other::class.java != this::class.java) return false
if (!super.equals(other)) return false
other as StrictBasicValue

View File

@@ -17,8 +17,10 @@
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
val AbstractInsnNode.isMeaningful: Boolean get() =
@@ -50,9 +52,7 @@ fun MethodNode.prepareForEmitting() {
// local variables with live ranges starting after last meaningful instruction lead to VerifyError
localVariables = localVariables.filter { lv ->
InsnSequence(lv.start, lv.end).any { insn ->
insn.isMeaningful
}
InsnSequence(lv.start, lv.end).any(AbstractInsnNode::isMeaningful)
}
// We should remove linenumbers after last meaningful instruction
@@ -71,10 +71,64 @@ fun MethodNode.prepareForEmitting() {
fun MethodNode.removeEmptyCatchBlocks() {
tryCatchBlocks = tryCatchBlocks.filter { tcb ->
InsnSequence(tcb.start, tcb.end).any { insn ->
insn.isMeaningful
InsnSequence(tcb.start, tcb.end).any(AbstractInsnNode::isMeaningful)
}
}
fun MethodNode.removeUnusedLocalVariables() {
val used = BooleanArray(maxLocals) { false }
for (insn in instructions) {
when (insn) {
is VarInsnNode -> {
val varIndex = insn.`var`
used[varIndex] = true
if (insn.isSize2LoadStoreOperation()) {
used[varIndex + 1] = true
}
}
is IincInsnNode ->
used[insn.`var`] = true
}
}
for (localVar in localVariables) {
val varIndex = localVar.index
used[varIndex] = true
val type = Type.getType(localVar.desc)
if (type.size == 2) {
used[varIndex + 1] = true
}
}
if (used.all { it }) return
val remapping = IntArray(maxLocals) { 0 }
var lastUnused = 0
for (i in remapping.indices) {
remapping[i] = lastUnused
if (used[i]) {
lastUnused++
}
}
remapLocalVariables(remapping)
}
private fun VarInsnNode.isSize2LoadStoreOperation() =
opcode == LLOAD || opcode == DLOAD || opcode == LSTORE || opcode == DSTORE
fun MethodNode.remapLocalVariables(remapping: IntArray) {
for (insn in instructions.toArray()) {
when (insn) {
is VarInsnNode ->
insn.`var` = remapping[insn.`var`]
is IincInsnNode ->
insn.`var` = remapping[insn.`var`]
}
}
for (localVariableNode in localVariables) {
localVariableNode.index = remapping[localVariableNode.index]
}
}
inline fun AbstractInsnNode.findNextOrNull(predicate: (AbstractInsnNode) -> Boolean): AbstractInsnNode? {
@@ -119,9 +173,16 @@ val AbstractInsnNode.intConstant: Int? get() =
fun insnListOf(vararg insns: AbstractInsnNode) = InsnList().apply { insns.forEach { add(it) } }
fun AbstractInsnNode.isStoreOperation(): Boolean = getOpcode() in Opcodes.ISTORE..Opcodes.ASTORE
fun AbstractInsnNode.isLoadOperation(): Boolean = getOpcode() in Opcodes.ILOAD..Opcodes.ALOAD
fun AbstractInsnNode.isStoreOperation(): Boolean = opcode in Opcodes.ISTORE..Opcodes.ASTORE
fun AbstractInsnNode.isLoadOperation(): Boolean = opcode in Opcodes.ILOAD..Opcodes.ALOAD
val AbstractInsnNode?.insnText get() = InlineCodegenUtil.getInsnText(this)
val AbstractInsnNode?.debugText get() =
if (this == null) "<null>" else "${this.javaClass.simpleName}: $insnText"
if (this == null) "<null>" else "${this::class.java.simpleName}: $insnText"
internal inline fun <reified T : AbstractInsnNode> AbstractInsnNode.isInsn(opcode: Int, condition: T.() -> Boolean): Boolean =
takeInsnIf(opcode, condition) != null
internal inline fun <reified T : AbstractInsnNode> AbstractInsnNode.takeInsnIf(opcode: Int, condition: T.() -> Boolean): T? =
takeIf { it.opcode == opcode }?.safeAs<T>()?.takeIf { it.condition() }

View File

@@ -58,16 +58,9 @@ internal class FixStackAnalyzer(
for (marker in context.fakeAlwaysFalseIfeqMarkers) {
val next = marker.next
if (next is JumpInsnNode) {
val nop = InsnNode(Opcodes.NOP)
expectedStackNode[next.label] = nop
method.instructions.insert(next, nop)
method.instructions.remove(marker)
method.instructions.remove(next)
context.nodesToRemoveOnCleanup.add(nop)
expectedStackNode[next.label] = marker
}
}
context.fakeAlwaysFalseIfeqMarkers.clear()
}
private val analyzer = InternalAnalyzer(owner, method, context)

View File

@@ -39,8 +39,6 @@ internal class FixStackContext(val methodNode: MethodNode) {
val openingInlineMethodMarker = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
var consistentInlineMarkers: Boolean = true; private set
val nodesToRemoveOnCleanup = arrayListOf<AbstractInsnNode>()
init {
saveStackMarkerForRestoreMarker = insertTryCatchBlocksMarkers(methodNode)
isThereAnyTryCatch = saveStackMarkerForRestoreMarker.isNotEmpty()

View File

@@ -39,31 +39,51 @@ class FixStackMethodTransformer : MethodTransformer() {
}
if (context.isAnalysisRequired()) {
val analyzer = FixStackAnalyzer(internalClassName, methodNode, context)
analyzer.analyze()
methodNode.maxStack = methodNode.maxStack + analyzer.maxExtraStackSize
val actions = arrayListOf<() -> Unit>()
transformBreakContinueGotos(methodNode, context, actions, analyzer)
transformSaveRestoreStackMarkers(methodNode, context, actions, analyzer)
actions.forEach { it() }
analyzeAndTransformBreakContinueGotos(context, internalClassName, methodNode)
removeAlwaysFalseIfeqMarkers(context, methodNode)
analyzeAndTransformSaveRestoreStack(context, internalClassName, methodNode)
}
context.fakeAlwaysTrueIfeqMarkers.forEach { marker ->
replaceAlwaysTrueIfeqWithGoto(methodNode, marker)
}
removeAlwaysTrueIfeqMarkers(context, methodNode)
removeAlwaysFalseIfeqMarkers(context, methodNode)
}
private fun analyzeAndTransformBreakContinueGotos(context: FixStackContext, internalClassName: String, methodNode: MethodNode) {
val analyzer = FixStackAnalyzer(internalClassName, methodNode, context)
analyzer.analyze()
methodNode.maxStack = methodNode.maxStack + analyzer.maxExtraStackSize
val actions = arrayListOf<() -> Unit>()
transformBreakContinueGotos(methodNode, context, actions, analyzer)
actions.forEach { it() }
}
private fun analyzeAndTransformSaveRestoreStack(context: FixStackContext, internalClassName: String, methodNode: MethodNode) {
val analyzer = FixStackAnalyzer(internalClassName, methodNode, context)
analyzer.analyze()
val actions = arrayListOf<() -> Unit>()
transformSaveRestoreStackMarkers(methodNode, context, actions, analyzer)
actions.forEach { it() }
}
private fun removeAlwaysFalseIfeqMarkers(context: FixStackContext, methodNode: MethodNode) {
context.fakeAlwaysFalseIfeqMarkers.forEach { marker ->
removeAlwaysFalseIfeq(methodNode, marker)
}
context.fakeAlwaysFalseIfeqMarkers.clear()
}
context.nodesToRemoveOnCleanup.forEach {
methodNode.instructions.remove(it)
private fun removeAlwaysTrueIfeqMarkers(context: FixStackContext, methodNode: MethodNode) {
context.fakeAlwaysTrueIfeqMarkers.forEach { marker ->
replaceAlwaysTrueIfeqWithGoto(methodNode, marker)
}
context.fakeAlwaysTrueIfeqMarkers.clear()
}
private fun transformBreakContinueGotos(

View File

@@ -26,7 +26,7 @@ fun <V : Value> Frame<V>.top(): V? =
peek(0)
fun <V : Value> Frame<V>.peek(offset: Int): V? =
if (stackSize >= offset) getStack(stackSize - offset - 1) else null
if (stackSize > offset) getStack(stackSize - offset - 1) else null
class SavedStackDescriptor(
val savedValues: List<BasicValue>,

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.nullCheck
import org.jetbrains.kotlin.codegen.optimization.boxing.*
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
class NullabilityInterpreter : OptimizationBasicInterpreter() {
override fun newOperation(insn: AbstractInsnNode): BasicValue? {
val defaultResult = super.newOperation(insn)
val resultType = defaultResult?.type
return when {
insn.opcode == Opcodes.ACONST_NULL ->
NullBasicValue
insn.opcode == Opcodes.NEW ->
NotNullBasicValue(resultType)
insn.opcode == Opcodes.LDC && resultType.isReferenceType() ->
NotNullBasicValue(resultType)
insn.isUnitInstance() ->
NotNullBasicValue(resultType)
else ->
defaultResult
}
}
private fun Type?.isReferenceType() =
this?.sort.let { it == Type.OBJECT || it == Type.ARRAY }
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? {
val defaultResult = super.unaryOperation(insn, value)
val resultType = defaultResult?.type
return when {
insn.opcode == Opcodes.CHECKCAST ->
value
insn.opcode == Opcodes.NEWARRAY || insn.opcode == Opcodes.ANEWARRAY ->
NotNullBasicValue(resultType)
else ->
defaultResult
}
}
override fun naryOperation(insn: AbstractInsnNode, values: List<BasicValue>): BasicValue? {
val defaultResult = super.naryOperation(insn, values)
val resultType = defaultResult?.type
return when {
insn.isBoxing() ->
NotNullBasicValue(resultType)
insn.isIteratorMethodCallOfProgression(values) ->
ProgressionIteratorBasicValue.byProgressionClassType(values[0].type)
insn.isNextMethodCallOfProgressionIterator(values) ->
NotNullBasicValue(resultType)
else ->
defaultResult
}
}
override fun merge(v: BasicValue, w: BasicValue): BasicValue =
when {
v is NullBasicValue && w is NullBasicValue ->
NullBasicValue
v is NullBasicValue || w is NullBasicValue ->
StrictBasicValue.REFERENCE_VALUE
v is ProgressionIteratorBasicValue && w is ProgressionIteratorBasicValue ->
mergeNotNullValuesOfSameKind(v, w)
v is ProgressionIteratorBasicValue && w is NotNullBasicValue ->
NotNullBasicValue.NOT_NULL_REFERENCE_VALUE
w is ProgressionIteratorBasicValue && v is NotNullBasicValue ->
NotNullBasicValue.NOT_NULL_REFERENCE_VALUE
v is NotNullBasicValue && w is NotNullBasicValue ->
mergeNotNullValuesOfSameKind(v, w)
else ->
super.merge(v, w)
}
private fun mergeNotNullValuesOfSameKind(v: StrictBasicValue, w: StrictBasicValue) =
if (v.type == w.type) v else NotNullBasicValue.NOT_NULL_REFERENCE_VALUE
}
fun TypeInsnNode.getObjectType(): Type =
Type.getObjectType(desc)

View File

@@ -0,0 +1,97 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.nullCheck
import org.jetbrains.kotlin.codegen.optimization.DeadCodeEliminationMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.ProgressionIteratorBasicValue
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.InsnNode
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
class RedundantNullCheckMethodTransformer : MethodTransformer() {
private val deadCodeElimination = DeadCodeEliminationMethodTransformer()
override fun transform(internalClassName: String, methodNode: MethodNode) {
while (runSingleNullCheckEliminationPass(internalClassName, methodNode)) {
deadCodeElimination.transform(internalClassName, methodNode)
}
}
private fun isAlwaysFalse(opcode: Int, nullability: Nullability) =
(opcode == Opcodes.IFNULL && nullability == Nullability.NOT_NULL) ||
(opcode == Opcodes.IFNONNULL && nullability == Nullability.NULL)
private fun isAlwaysTrue(opcode: Int, nullability: Nullability) =
(opcode == Opcodes.IFNULL && nullability == Nullability.NULL) ||
(opcode == Opcodes.IFNONNULL && nullability == Nullability.NOT_NULL)
private fun runSingleNullCheckEliminationPass(internalClassName: String, methodNode: MethodNode): Boolean {
val insnList = methodNode.instructions
val instructions = insnList.toArray()
val nullCheckIfs = instructions.mapNotNullTo(SmartList<JumpInsnNode>()) {
it.safeAs<JumpInsnNode>()?.takeIf {
it.opcode == Opcodes.IFNULL ||
it.opcode == Opcodes.IFNONNULL
}
}
if (nullCheckIfs.isEmpty()) return false
val frames = analyze(internalClassName, methodNode, NullabilityInterpreter())
val redundantNullCheckIfs = nullCheckIfs.mapNotNull { insn ->
frames[instructions.indexOf(insn)]?.top()?.let { top ->
val nullability = top.getNullability()
if (nullability == Nullability.NULLABLE)
null
else
Pair(insn, nullability)
}
}
if (redundantNullCheckIfs.isEmpty()) return false
for ((insn, nullability) in redundantNullCheckIfs) {
val previous = insn.previous
when (previous?.opcode) {
Opcodes.ALOAD, Opcodes.DUP ->
insnList.remove(previous)
else ->
insnList.insert(previous, InsnNode(Opcodes.POP))
}
when {
isAlwaysTrue(insn.opcode, nullability) ->
insnList.set(insn, JumpInsnNode(Opcodes.GOTO, insn.label))
isAlwaysFalse(insn.opcode, nullability) ->
insnList.remove(insn)
}
}
return true
}
}

View File

@@ -0,0 +1,367 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.nullCheck
import org.jetbrains.kotlin.codegen.coroutines.withInstructionAdapter
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.codegen.optimization.DeadCodeEliminationMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.isInsn
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.*
class RedundantNullCheckV2MethodTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
while (TransformerPass(internalClassName, methodNode).run()) {}
}
private class TransformerPass(val internalClassName: String, val methodNode: MethodNode) {
private var changes = false
private fun AbstractInsnNode.getIndex() =
methodNode.instructions.indexOf(this)
fun run(): Boolean {
val checkedReferenceTypes = analyzeTypesAndRemoveDeadCode()
eliminateRedundantChecks(checkedReferenceTypes)
return changes
}
private fun analyzeTypesAndRemoveDeadCode(): Map<AbstractInsnNode, Type> {
val insns = methodNode.instructions.toArray()
val frames = analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
val checkedReferenceTypes = HashMap<AbstractInsnNode, Type>()
for (i in insns.indices) {
val insn = insns[i]
val frame = frames[i]
if (insn.isInstanceOfOrNullCheck()) {
checkedReferenceTypes[insn] = frame?.top()?.type ?: continue
}
else if (insn.isCheckParameterNotNull()) {
checkedReferenceTypes[insn] = frame?.peek(1)?.type ?: continue
}
}
val dceResult = DeadCodeEliminationMethodTransformer().removeDeadCodeByFrames(methodNode, frames)
if (dceResult.hasRemovedAnything()) {
changes = true
}
return checkedReferenceTypes
}
private fun eliminateRedundantChecks(checkedReferenceTypes: Map<AbstractInsnNode, Type>) {
val nullabilityAssumptions = injectNullabilityAssumptions(checkedReferenceTypes)
val nullabilityMap = analyzeNullabilities()
nullabilityAssumptions.revert()
transformTrivialChecks(nullabilityMap)
}
private fun injectNullabilityAssumptions(checkedReferenceTypes: Map<AbstractInsnNode, Type>) =
NullabilityAssumptionsBuilder(checkedReferenceTypes).injectNullabilityAssumptions()
private fun analyzeNullabilities(): Map<AbstractInsnNode, Nullability> {
val frames = analyze(internalClassName, methodNode, NullabilityInterpreter())
val insns = methodNode.instructions.toArray()
val nullabilityMap = HashMap<AbstractInsnNode, Nullability>()
for (i in insns.indices) {
val nullability = frames[i]?.top()?.getNullability() ?: continue
if (nullability == Nullability.NULLABLE) continue
val insn = insns[i]
if (insn.isInstanceOfOrNullCheck()) {
nullabilityMap[insn] = nullability
}
}
return nullabilityMap
}
private fun transformTrivialChecks(nullabilityMap: Map<AbstractInsnNode, Nullability>) {
for ((insn, nullability) in nullabilityMap) {
when (insn.opcode) {
Opcodes.IFNULL -> transformTrivialNullJump(insn as JumpInsnNode, nullability == Nullability.NULL)
Opcodes.IFNONNULL -> transformTrivialNullJump(insn as JumpInsnNode, nullability == Nullability.NOT_NULL)
Opcodes.INSTANCEOF -> transformInstanceOf(insn, nullability)
}
}
}
private fun transformTrivialNullJump(insn: JumpInsnNode, alwaysTrue: Boolean) {
changes = true
methodNode.instructions.run {
popReferenceValueBefore(insn)
if (alwaysTrue) {
set(insn, JumpInsnNode(Opcodes.GOTO, insn.label))
}
else {
remove(insn)
}
}
}
private fun transformInstanceOf(insn: AbstractInsnNode, nullability: Nullability) {
if (nullability != Nullability.NULL) return
if (ReifiedTypeInliner.isOperationReifiedMarker(insn.previous)) return
changes = true
val nextOpcode = insn.next?.opcode
if (nextOpcode == Opcodes.IFEQ || nextOpcode == Opcodes.IFNE)
transformNullInstanceOfWithJump(insn)
else
transformNullInstanceOf(insn)
}
private fun transformNullInstanceOf(insn: AbstractInsnNode) {
methodNode.instructions.run {
popReferenceValueBefore(insn)
set(insn, InsnNode(Opcodes.ICONST_0))
}
}
private fun transformNullInstanceOfWithJump(insn: AbstractInsnNode) {
methodNode.instructions.run {
popReferenceValueBefore(insn)
val jump = insn.next.assertedCast<JumpInsnNode> { "JumpInsnNode expected" }
remove(insn)
if (jump.opcode == Opcodes.IFEQ) {
set(jump, JumpInsnNode(Opcodes.GOTO, jump.label))
}
else {
remove(jump)
}
}
}
private inner class NullabilityAssumptionsBuilder(val checkedReferenceTypes: Map<AbstractInsnNode, Type>) {
private val checksDependingOnVariable = HashMap<Int, MutableList<AbstractInsnNode>>()
fun injectNullabilityAssumptions(): NullabilityAssumptions {
collectVariableDependentChecks()
return injectAssumptions()
}
private fun collectVariableDependentChecks() {
for (insn in methodNode.instructions) {
if (insn.isInstanceOfOrNullCheck()) {
val previous = insn.previous ?: continue
if (previous.opcode == Opcodes.ALOAD) {
addDependentCheck(insn, previous as VarInsnNode)
}
else if (previous.opcode == Opcodes.DUP) {
val previous2 = previous.previous ?: continue
if (previous2.opcode == Opcodes.ALOAD) {
addDependentCheck(insn, previous2 as VarInsnNode)
}
}
}
else if (insn.isCheckParameterNotNull()) {
val ldcInsn = insn.previous ?: continue
if (ldcInsn.opcode != Opcodes.LDC) continue
val aLoadInsn = ldcInsn.previous ?: continue
if (aLoadInsn.opcode != Opcodes.ALOAD) continue
addDependentCheck(insn, aLoadInsn as VarInsnNode)
}
}
}
private fun addDependentCheck(insn: AbstractInsnNode, aLoadInsn: VarInsnNode) {
checksDependingOnVariable.getOrPut(aLoadInsn.`var`) {
SmartList<AbstractInsnNode>()
}.add(insn)
}
private fun injectAssumptions(): NullabilityAssumptions {
val nullabilityAssumptions = NullabilityAssumptions()
for ((varIndex, dependentChecks) in checksDependingOnVariable) {
for (checkInsn in dependentChecks) {
val varType = checkedReferenceTypes[checkInsn]
?: throw AssertionError("No var type @${checkInsn.getIndex()}")
nullabilityAssumptions.injectAssumptionsForCheck(varIndex, checkInsn, varType)
}
}
return nullabilityAssumptions
}
private fun NullabilityAssumptions.injectAssumptionsForCheck(varIndex: Int, insn: AbstractInsnNode, varType: Type) {
when (insn.opcode) {
Opcodes.IFNULL,
Opcodes.IFNONNULL ->
injectAssumptionsForNullCheck(varIndex, insn as JumpInsnNode, varType)
Opcodes.INVOKESTATIC -> {
assert(insn.isCheckParameterNotNull()) { "Expected non-null parameter check @${insn.getIndex()}"}
injectAssumptionsForParameterNotNullCheck(varIndex, insn, varType)
}
Opcodes.INSTANCEOF ->
injectAssumptionsForInstanceOfCheck(varIndex, insn, varType)
}
}
private fun NullabilityAssumptions.injectAssumptionsForNullCheck(varIndex: Int, insn: JumpInsnNode, varType: Type) {
// ALOAD v
// IFNULL L
// <...> -- v is not null here
// L:
// <...> -- v is null here
val jumpsIfNull = insn.opcode == Opcodes.IFNULL
val originalLabel = insn.label
originalLabels[insn] = originalLabel
insn.label = synthetic(LabelNode(Label()))
val insertAfterNull = if (jumpsIfNull) insn.label else insn
val insertAfterNonNull = if (jumpsIfNull) insn else insn.label
methodNode.instructions.run {
add(insn.label)
insert(insertAfterNull, listOfSynthetics {
aconst(null)
store(varIndex, varType)
if (jumpsIfNull) {
goTo(originalLabel.label)
}
})
insert(insertAfterNonNull, listOfSynthetics {
anew(varType)
store(varIndex, varType)
if (!jumpsIfNull) {
goTo(originalLabel.label)
}
})
}
}
private fun NullabilityAssumptions.injectAssumptionsForParameterNotNullCheck(varIndex: Int, insn: AbstractInsnNode, varType: Type) {
// ALOAD v
// LDC param_name
// INVOKESTATIC checkParameterIsNotNull
// <...> -- v is not null here (otherwise an exception was thrown)
methodNode.instructions.insert(insn, listOfSynthetics {
anew(varType)
store(varIndex, varType)
})
}
private fun NullabilityAssumptions.injectAssumptionsForInstanceOfCheck(varIndex: Int, insn: AbstractInsnNode, varType: Type) {
// ALOAD v
// INSTANCEOF T
// IFEQ L
// <...> -- v is not null here (because it is an instance of T)
// L:
// <...> -- v is something else here (maybe null)
val next = insn.next ?: return
if (next.opcode != Opcodes.IFEQ && next.opcode != Opcodes.IFNE) return
if (next !is JumpInsnNode) return
val jumpsIfInstance = next.opcode == Opcodes.IFNE
val originalLabel: LabelNode?
val insertAfterNotNull: AbstractInsnNode
if (jumpsIfInstance) {
originalLabel = next.label
originalLabels[next] = next.label
val newLabel = synthetic(LabelNode(Label()))
methodNode.instructions.add(newLabel)
next.label = newLabel
insertAfterNotNull = newLabel
}
else {
originalLabel = null
insertAfterNotNull = next
}
methodNode.instructions.run {
insert(insertAfterNotNull, listOfSynthetics {
anew(varType)
store(varIndex, varType)
if (originalLabel != null) {
goTo(originalLabel.label)
}
})
}
}
}
inner class NullabilityAssumptions {
val originalLabels = HashMap<JumpInsnNode, LabelNode>()
val syntheticInstructions = ArrayList<AbstractInsnNode>()
fun <T : AbstractInsnNode> synthetic(insn: T): T {
syntheticInstructions.add(insn)
return insn
}
inline fun listOfSynthetics(block: InstructionAdapter.() -> Unit): InsnList {
val insnList = withInstructionAdapter(block)
for (insn in insnList) {
synthetic(insn)
}
return insnList
}
fun revert() {
methodNode.instructions.run {
syntheticInstructions.forEach { remove(it) }
}
for ((jumpInsn, originalLabel) in originalLabels) {
jumpInsn.label = originalLabel
}
}
}
}
}
internal fun AbstractInsnNode.isInstanceOfOrNullCheck() =
opcode == Opcodes.INSTANCEOF || opcode == Opcodes.IFNULL || opcode == Opcodes.IFNONNULL
internal fun AbstractInsnNode.isCheckParameterNotNull() =
isInsn<MethodInsnNode>(Opcodes.INVOKESTATIC) {
owner == "kotlin/jvm/internal/Intrinsics" &&
name == "checkParameterIsNotNull" &&
desc == "(Ljava/lang/Object;Ljava/lang/String;)V"
}
internal fun InsnList.popReferenceValueBefore(insn: AbstractInsnNode) {
val prev = insn.previous
when (prev?.opcode) {
Opcodes.ACONST_NULL,
Opcodes.DUP,
Opcodes.ALOAD ->
remove(prev)
else ->
insertBefore(insn, InsnNode(Opcodes.POP))
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.optimization.nullCheck
import org.jetbrains.kotlin.codegen.optimization.boxing.ProgressionIteratorBasicValue
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
class NotNullBasicValue(type: Type?) : StrictBasicValue(type) {
override fun equals(other: Any?): Boolean = other is NotNullBasicValue
// We do not differ not-nullable values, so we should always return the same hashCode
// Actually it doesn't really matter because analyzer is not supposed to store values in hashtables
override fun hashCode() = 0
companion object {
val NOT_NULL_REFERENCE_VALUE = NotNullBasicValue(StrictBasicValue.REFERENCE_VALUE.type)
}
}
object NullBasicValue : StrictBasicValue(AsmTypes.OBJECT_TYPE)
enum class Nullability {
NULL, NOT_NULL, NULLABLE;
fun isNull() = this == NULL
fun isNotNull() = this == NOT_NULL
}
fun BasicValue.getNullability(): Nullability =
when (this) {
is NullBasicValue -> Nullability.NULL
is NotNullBasicValue -> Nullability.NOT_NULL
is ProgressionIteratorBasicValue -> Nullability.NOT_NULL
else -> Nullability.NULLABLE
}

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