Compare commits

...

82 Commits

Author SHA1 Message Date
Natalia Selezneva
bdcbf49610 Replace missing property from GradleConstants 2018-04-06 16:57:13 +02:00
Nicolay Mitropolsky
82ae6b4f05 psiModificationUtils.kt: compilation fixes 2018-04-06 16:57:12 +02:00
Nikolay Krasko
b9148948da Revert "UAST: support for JvmDeclarationUElement"
This reverts commit db6a2390a22d4b35246cc4c6d246a5d7752f3506.
2018-04-06 16:57:12 +02:00
Nikolay Krasko
55247d6944 Revert "Data Inflow: Support grouping by leaf expressions"
This reverts commit d5af2db2f259c7d55d38be73b9a5136e3aefd580.
2018-04-06 16:57:11 +02:00
Mikhael Bogdanov
c9b510ce4b Fix compilation 2018-04-06 16:57:11 +02:00
Nikolay Krasko
a1fe66c819 Restore KotlinCommonCodeStyleSettings behaviour for 172 Idea
There are no soft margins in CommonCodeStyleSettings.
2018-04-06 16:57:10 +02:00
Nikolay Krasko
2d598ea639 Fix compilation in 172 after AbstractApplicationUsagesCollector rename
See c299f7d10a93a055cc868a9d9d20d68cc47c35e3 to intellij_community
2018-04-06 16:57:10 +02:00
Nicolay Mitropolsky
924f24b189 Uast-revert: test-data-revert 2018-04-06 16:57:10 +02:00
Nicolay Mitropolsky
f81cc4bb72 Uast-revert: reverting to previous rebase state 2018-04-06 16:57:09 +02:00
Nicolay Mitropolsky
9eccb4d9d2 Uast-revert: AbstractKotlinRenderLogTest 2018-04-06 16:57:09 +02:00
Nicolay Mitropolsky
9b724f31b9 AbstractSlicerTest.kt reverted to previous rebase 2018-04-06 16:57:09 +02:00
Nicolay Mitropolsky
aa346aa77d KotlinUCollectionLiteralExpression: remove override modifier 2018-04-06 16:57:08 +02:00
Nicolay Mitropolsky
de664c234e IDEA-172-related compilation fix PluginTestCaseBase.addJdk(myFixture.projectDisposable 2018-04-06 16:57:08 +02:00
Natalia Selezneva
04b9e4be4d Remove textAttributes parameter from EditorCustomElementRenderer:paint 2018-04-06 16:57:08 +02:00
Nikolay Krasko
4f4f1c3b3c Restore usage of PathUtil.getLocalFile in 172 idea
There's no VfsUtil.getLocalFile
2018-04-06 16:57:07 +02:00
Vyacheslav Gerasimov
af52dd19c5 Set intellijSdk to 172.4343.14 2018-04-06 16:57:07 +02:00
Vyacheslav Gerasimov
f35bd41c88 Revert "UAST: override getFunctionalInterfaceType + test"
This reverts commit 92c23aa
2018-04-06 16:57:06 +02:00
Vyacheslav Gerasimov
ca03f13c5c Revert "Quick Fixes: Support cross-language "Create from Usage" with Kotlin target"
This reverts commit 908bf71
2018-04-06 16:57:06 +02:00
Vyacheslav Gerasimov
25ead7e78d Revert "Quick Fixes: Drop deprecated KotlinCommonIntentionActionsFactory"
This reverts commit ba0a91d
2018-04-06 16:57:05 +02:00
Vyacheslav Gerasimov
7f9c7bc8d5 Revert "Refactoring: Use modifier list in CallableInfo where possible"
This reverts commit 99be75c
2018-04-06 16:57:04 +02:00
Nikolay Krasko
061a484790 Try to remove unneeded commits in 172 branch
Revert "[Unneeded?] Revert "ExpressionOfTypeProcessor: get member name in read action""
This reverts commit 7ec59fc

Revert "[Unneeded] Revert "AbstractNavigateToLibraryTest: fix for invalid files""
This reverts commit 9e80c60

Revert "[Unneeded?] Revert "AbstractExtractionTest: fix for invalid files""
This reverts commit 0b2113b

Revert "[Unneeded] Revert "AbstractIntentionTest: `isApplicableOnPooled` made run under ProgressIndicator""
This reverts commit a41c247
2018-04-06 16:57:03 +02:00
Nikolay Krasko
c06f150187 [Unneeded?] Revert "ExpressionOfTypeProcessor: get member name in read action"
This reverts commit 32d8e0c72b877f0c0123bb56e0d92beaab410daa.
2018-04-06 16:57:02 +02:00
Nikolay Krasko
d0a15721b3 [Unneeded] Revert "AbstractNavigateToLibraryTest: fix for invalid files"
This reverts commit e71b1757be6ca4b9ef49d65c6250a94f5f724f53.
2018-04-06 16:57:01 +02:00
Nikolay Krasko
eb66af98f0 [Unneeded?] Revert "AbstractExtractionTest: fix for invalid files"
This reverts commit b3b71ac53bb5150457ff228ecccb15060dd2de1f.
2018-04-06 16:57:01 +02:00
Nikolay Krasko
e1c4a62365 [Unneeded] Revert "AbstractIntentionTest: isApplicableOnPooled made run under ProgressIndicator"
This reverts commit d1ad207fdbed6698ec352bd8b759f9ae62baebb3.
2018-04-06 16:57:00 +02:00
Nikolay Krasko
ad78c11432 Revert "UAST: Properly handle annotations on local variables"
This reverts commit 70de7cff5e23abf723009c8df8bc2df2f646a675.
2018-04-06 16:56:59 +02:00
Nikolay Krasko
e959429408 Revert "UAST: Add testConvertTypeInAnnotation"
This reverts commit 7d1b28b2b6bc80411ef19bb7619181bee637cf20.
2018-04-06 16:56:58 +02:00
Nikolay Krasko
5f2e8a4d4a Revert "UAST: Fix testPropertyWithAnnotation"
This reverts commit 36a405cb55198592ee017c7eed9bd50fd6433f22.
2018-04-06 16:56:57 +02:00
Nikolay Krasko
4667836852 Revert "UAST test data fixes: @null in render"
This reverts commit 2f366b8209206b32792919f35f896fc63ad4b0e5.
2018-04-06 16:56:57 +02:00
Nikolay Krasko
8da5ae155e Revert "UAST test data fixes: LocalVariableWithAnnotationKt fix for variable type"
This reverts commit ef61beb53ae1030afe11b3d15a2750959136ad65.
2018-04-06 16:56:56 +02:00
Nikolay Krasko
2134c4d207 Revert "UAST: support for JvmDeclarationUElement"
This reverts commit db6a2390a22d4b35246cc4c6d246a5d7752f3506.
2018-04-06 16:56:56 +02:00
Nikolay Krasko
3551d537a0 Revert "UAST: SimpleKotlinRenderLogTest.testWhenAndDestructing testdata fix"
This reverts commit c6c71dc5e82e5eec547fb6fe3fe6eb578e8183c9.
2018-04-06 16:56:55 +02:00
Nikolay Krasko
56b40b9725 Revert "UAST: StringTemplateComplex testdata fix"
This reverts commit 2ef0be9b2af14438aa7d899f78e2da327e9a8a07.
2018-04-06 16:56:55 +02:00
Nikolay Krasko
5266db3767 Revert "Uast: AbstractKotlinUClass compilation fix"
This reverts commit 86ee036ae7d89f8acc885d54157d9b9ce5f2cb17.
2018-04-06 16:56:54 +02:00
Nikolay Krasko
cf130b0648 Revert "Uast: SuperCalls.render.txt testdata fix"
This reverts commit 28a0267dc131ab37ede64f38de0dc2722aba1762.
2018-04-06 16:56:54 +02:00
Nikolay Krasko
fb14e3996c Revert "Uast: Constructors.kt testData fixes"
This reverts commit 0d35e32b1ee7006b9c9febf1f8992fbbe3246230.
2018-04-06 16:56:54 +02:00
Nikolay Krasko
c8aaae29d8 Revert "Uast: WrappedUAnnotation as replacement for usage of JavaUAnnotation (KT-21025)"
This reverts commit 9701403889fbed93d9ea1e8fa4df58c720b3be72.
2018-04-06 16:56:53 +02:00
Nikolay Krasko
94ab177ef6 Revert "Uast: AbstractKotlinUVariable annotations now are retrieved from Kotlin Psi, not from compiled (KT-21025)"
This reverts commit ebbfc4a3845159ba8f0e3d94a5f70489c348c403.
2018-04-06 16:56:53 +02:00
Nikolay Krasko
14a6863848 Revert "Uast: removing java-uast usage from KotlinUastLanguagePlugin and KotlinEnumConstantClassReference"
This reverts commit dfab8a6888a44d41253477eefb5db75368bb0803.
2018-04-06 16:56:52 +02:00
Nikolay Krasko
39d2ca6ad5 Revert "Uast: making AbstractKotlinUClass not inherit from AbstractJavaUClass"
This reverts commit d35f79963c810365451f09e98c148f9ce7fc3263.
2018-04-06 16:56:52 +02:00
Nikolay Krasko
43fbcd22e6 Revert "Uast: no more need to exclude UIdentifier from JvmDeclarationUElement check"
This reverts commit a92791a1f3cdec9ece602c5778eb04d5ffbd7505.
2018-04-06 16:56:51 +02:00
Nikolay Krasko
03b92adefe Revert "Uast: uastParent made final in KotlinAbstractUElement"
This reverts commit 9b006787581cca8167714d07ad36aea195ff9c02.
2018-04-06 16:56:51 +02:00
Nikolay Krasko
f17603acc3 Revert "Uast: Constructors.kt testdata fixes"
This reverts commit a725f43588a6d2f2d1c79649f46849f8cbabbc8f.
2018-04-06 16:56:50 +02:00
Nikolay Krasko
cc0cabfb39 Revert "Uast: handling @receiver annotations"
This reverts commit 2f3b1485a30442db016e7f529d273483315067cf.
2018-04-06 16:56:50 +02:00
Nikolay Krasko
3f57f182e0 Revert "Uast: KotlinAccessorCallExpression made implement JvmDeclarationUElement"
This reverts commit f75a5d8372ab3041d8a1a8073beaa96a79a50b03.
2018-04-06 16:56:49 +02:00
Nikolay Krasko
37527679c2 [Spring] Revert "Fixes for 173 after 28.08.17 changes in IDEA (#1271)"
This reverts commit 3a37d18e5d65043fc99a28772303d948e0f89f6c.
2018-04-06 16:56:49 +02:00
Nikolay Krasko
10f4bbb940 [Spring] Revert "Spring-Kotlin: Gutter repaired (KT-20550, KT-20566)"
This reverts commit 37752694df794cc07492d21a3924ee735e6d3b9d.
2018-04-06 16:56:48 +02:00
Nikolay Krasko
5083f4264e [Srping] Revert "Spring gutter icons SpringApiIcons -> SpringApiIcons.Gutter fix."
This reverts commit 2323e9dc75dbdf109564f1a0d28494e6b5e41075.
2018-04-06 16:56:48 +02:00
Nikolay Krasko
5e593e8226 [Spring?] Revert "SpringKotlinAutowiringInspection: getting rid of SpringJavaInjectionPointsAutowiringInspection"
This reverts commit d0446b0aed0707ef616484c9fda04915c08598b0.
2018-04-06 16:56:47 +02:00
Nikolay Krasko
f92fdb73a8 [Spring?] Revert "SpringTestFixtureExtension: option to forbid facet autoconfigure added"
This reverts commit 0c90753c5bd9ac3fa492a61589d2c8aad3b96cc1.
2018-04-06 16:56:46 +02:00
Nikolay Krasko
1bca6a9926 [Spring] Revert "KotlinSpringComponentScanInspection made to support platform JamReferenceContributor"
This reverts commit f6a3b2eae4b0c49359bb477b320bc433988bec37.
2018-04-06 16:56:45 +02:00
Nikolay Krasko
273310e40a [Spring] Revert "Spring: removing needless EP-s because they ported to UAST in platform"
This reverts commit 9355f79c6b06fdcd365f23b40e93ea841b372b27.
2018-04-06 16:56:44 +02:00
Nikolay Krasko
018991a69b Revert "Fix compilation after moving to idea 173"
This reverts commit fe121cc6aeadf63ca2c2819c9c7df59cc81caf5d.
2018-04-06 16:56:43 +02:00
Nikolay Krasko
39e86434d4 Restore compilation against Idea 172
Revert "Fix proguard settings for 173"
4dadae2e9c8419bfda9d77f56797e68edbd8ecd7.

Revert "Fix compilation in 173"
0633aa925c8e862519ae699e5e3fe81a2bd227c2.

Revert "Fix compilation (MockParameterInfoUIContext.java)"
01a7fbfb60d786c56c54f4fd77d9f1233f599ede.

Revert "Fix compilation"
043a5dac796f6bf92bbe6c9573c1af07fadcfe4e.

Revert "Fix compatibility with BuildScriptDataBuilder API changes"
c7df054d0e90a86fbe67f23802e9be49b2117ded.
2018-04-06 16:56:42 +02:00
Nikolay Krasko
7bbb777fa0 Restore KotlinCoreEnvironment for 172 branch
Revert "`KotlinCoreEnvironment`: set `ideaCompatibleBuildNumber = "173.1"`"
This reverts commit d3321cc77a6b55d8b8ff3c3a16473f2f3b378533.

Revert "`JvmFacade`-related tests repair"
This reverts commit faeacdd17d37a4d733b686f3a1d5e8fc6ea54d79.

Revert "Register new service and EPs added in 173"
This reverts commit 5d227c0e714c1b4316e7b8daca1f208ee423f448.
2018-04-06 16:56:42 +02:00
Nikolay Krasko
55f2283890 Revert "KtLightAbstractAnnotation build fix for 173 (#1283)"
This reverts commit b401cc19e07ad632d61ca0d402dc6017f9559d18.
2018-04-06 16:56:41 +02:00
Nikolay Krasko
eab5d7aa74 Revert 173 specific changes in language injection
Revert "`KotlinLanguageInjector` using Registry to enable annotation injections"
This reverts commit c16a1d598c2bacc849dd16fed974ccdbf8b80754.

Revert "`KotlinLanguageInjector#injectInAnnotationCall` optimization: using `PsiClassNamePatternCondition` to avoid calling `getResolvedCall`"
This reverts commit f9eaaeab61b1dd50de9341846e129b58eb47f247.

Revert "`KotlinLanguageInjector` can inject into files modified for autocompletion"
This reverts commit 7212b22b083023201700696d775355051321b120.

Revert "`KotlinLanguageInjector` understands patterns-injections into Java annotations"
This reverts commit 45847b515bdfd27cfa5d23ff8b9147054ffa6f60.
2018-04-06 16:56:41 +02:00
Nikolay Krasko
a0a5febc90 Revert "Fix GradleNoduleBuilder use qualified names check"
This reverts commit aec020a404d367195d58c7bb5d30185bfb85f202.
2018-04-06 16:56:40 +02:00
Nikolay Krasko
bfeee946cb Revert "idea-version set to since-build="173.1" until-build="181.*""
This reverts commit 48701780db05e3c0928521f5fb95a5b89d417d95.
2018-04-06 16:56:40 +02:00
Nikolay Krasko
dd38c1a8a2 Revert "Update file structure tests as FileStructurePopup api was changed in 173"
This reverts commit 5244d48fde8e373b046a8ccb602a280b946f8d41.
2018-04-06 16:56:39 +02:00
Nikolay Krasko
6b7094b8ea Revert "Workaround for CoreEnvironment initialization: explicitly setting versions for extensions"
This reverts commit 2e50bd19a83ab4a4f2b3a5d0cc09300ec1b7b1f7.
2018-04-06 16:56:39 +02:00
Nikolay Krasko
32329500e2 Revert "Fix find usages tests in 173 (run via ProgressIndicator)"
This reverts commit 1363306d562ad7ef5af9fd1642e139aa23abdd32.
2018-04-06 16:56:38 +02:00
Nikolay Krasko
0d51edcc02 Revert "AbstractJavaToKotlinConverterForWebDemoTest: setup fix: JvmElementProvider and JavaModuleSystem added"
This reverts commit e1f340f59a9ec83c38ad2a0fe32ba47dbf4cdfb1.
2018-04-06 16:56:38 +02:00
Nikolay Krasko
4140934233 Revert "EdtTestUtil.runInEdtAndWait fix for proper user action emulation"
This reverts commit 4ebe750d36e86545a72177f91dc3baaa235fa92d.
2018-04-06 16:56:38 +02:00
Nikolay Krasko
b584bde45d Revert "RecursiveMethodCallMarkerInfo and SuspendCallMarkerInfo forced to target Leaf-elements"
This reverts commit c78ec71e17c09ddb1094e44c84d9a1b92a3b509f.
2018-04-06 16:56:37 +02:00
Nikolay Krasko
b5338c9f40 Revert "AbstractQuickFixTest: FORCE_PACKAGE_FOLDER directive added"
This reverts commit 91e10ae8bb6d2748a7a8b02fa661daa4cb00d0f8.
2018-04-06 16:56:37 +02:00
Nikolay Krasko
cc42d924ee Revert "Ultimate-plugin: multiplePropertiesAnnotationConfig.kt test data fixes"
This reverts commit 4f2ee7359f8dfd3322329799475ff99dd88ed756.
2018-04-06 16:56:36 +02:00
Nikolay Krasko
de060dbc81 Revert "Drop new Kotlin Dsl gradle project wizard which has been merged to idea"
This reverts commit 742d337ad722fe6ddcd6ad5dab27d52eda970489.
2018-04-06 16:56:36 +02:00
Nikolay Krasko
4627b5e412 Revert "Fix formatting for new kotlin dsl gradle project build script"
This reverts commit 75a46e66d18f69ff196749ba436b572b4462ea0d.
2018-04-06 16:56:35 +02:00
Nikolay Krasko
f946fc481e Revert "Move: Fix applicability check in IDEA 173"
This reverts commit 74c28b2a564a859a20b3f799df24405ba634c175.
2018-04-06 16:56:35 +02:00
Nikolay Krasko
0555700daa Revert "Line Markers: Respect subclass module when filtering out duplicates"
This reverts commit 8df0a58586abf42572aff15d4bdd70e51e5cad29.
2018-04-06 16:56:32 +02:00
Nikolay Krasko
118dee51a5 Revert "Drop missing gradle extensions from gradle.xml"
This reverts commit 1f7a145942f0489e18b281878ac711e7505dce15.
2018-04-06 16:54:55 +02:00
Nikolay Krasko
86cc48f509 Revert "Update file name replace in QuickFix tests"
This reverts commit 01051618aa21c3502463c699f1d178136ef7c6b6.
2018-04-06 16:54:55 +02:00
Nikolay Krasko
39d23198ab Revert "Fix inAnnotation test in 173 branch"
This reverts commit 955842f2009a2c5aa9ac955340696bd7e1a2651d.
2018-04-06 16:54:55 +02:00
Nikolay Krasko
58b2f09cf6 Revert "Safe Delete: Suppress walking through light field initializer"
This reverts commit 34d3173ba79535591adb3e55a7af7cb9d1e49e40.
2018-04-06 16:54:54 +02:00
Nikolay Krasko
c18ead17b6 Revert "Data Inflow: Support grouping by leaf expressions"
This reverts commit d5af2db2f259c7d55d38be73b9a5136e3aefd580.
2018-04-06 16:54:54 +02:00
Nikolay Krasko
7c3a34c0cf Revert "Data Inflow: Support grouping by expression nullability"
This reverts commit e608f1ca159d55df39c8f33704220f360d54ba92.
2018-04-06 16:54:54 +02:00
Nikolay Krasko
8a8f01c4ad Revert "Fixing non-running tests, that used MockApplication environment"
This reverts commit 49fb7aab2a67f09c2832d759448ad07c1bb3023a.
2018-04-06 16:54:53 +02:00
Nikolay Krasko
5cb27c9fbf [172] Revert "Set correct until-build for Idea 173 plugin"
This reverts commit 0f378217684879491c3184b7db84e3ce3750a8b5.
2018-04-06 16:54:53 +02:00
Nikolay Krasko
190bae16e3 [Tests] Revert "Allow different diagnostics in Javac tests - workaround for IDEA-184289"
This reverts commit 5212153463dcefbde28b4ca1814f6888fa9c57c1.
2018-04-06 16:54:53 +02:00
Nikolay Krasko
53a58ed013 [Tests] Revert "Modify incremental test in 173 branch - files are not create anymore"
This reverts commit 0cc5d163d7d620565a28681dab31f3d3061a1324.
2018-04-06 16:54:52 +02:00
Nikolay Krasko
d5425608a1 == 173 -> 172 ^^^ == 2018-04-06 16:54:52 +02:00
339 changed files with 3111 additions and 5619 deletions

View File

@@ -28,7 +28,6 @@ import com.intellij.ide.highlighter.JavaFileType
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.lang.MetaLanguage
import com.intellij.lang.java.JavaParserDefinition
import com.intellij.lang.jvm.facade.JvmElementProvider
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.TransactionGuard
import com.intellij.openapi.application.TransactionGuardImpl
@@ -44,7 +43,6 @@ import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.*
import com.intellij.openapi.vfs.impl.ZipHandler
import com.intellij.psi.FileContextProvider
import com.intellij.psi.JavaModuleSystem
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiManager
import com.intellij.psi.augment.PsiAugmentProvider
@@ -395,7 +393,7 @@ class KotlinCoreEnvironment private constructor(
}
companion object {
private val ideaCompatibleBuildNumber = "173.1"
private val ideaCompatibleBuildNumber = "172.9999"
init {
setCompatibleBuild()
@@ -518,8 +516,6 @@ class KotlinCoreEnvironment private constructor(
//
CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier::class.java)
CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), MetaLanguage.EP_NAME, MetaLanguage::class.java)
//
CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), JavaModuleSystem.EP_NAME, JavaModuleSystem::class.java)
}
private fun registerApplicationExtensionPointsAndExtensionsFrom(configuration: CompilerConfiguration, configFilePath: String) {
@@ -570,7 +566,6 @@ class KotlinCoreEnvironment private constructor(
private fun registerProjectExtensionPoints(area: ExtensionsArea) {
CoreApplicationEnvironment.registerExtensionPoint(area, PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, PsiElementFinder.EP_NAME, PsiElementFinder::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, JvmElementProvider.EP_NAME, JvmElementProvider::class.java)
}
// made public for Upsource

View File

@@ -50,7 +50,6 @@ messages/**)
-dontwarn net.jpountz.lz4.LZ4Factory
-dontwarn org.jetbrains.annotations.ReadOnly
-dontwarn org.jetbrains.annotations.Mutable
-dontwarn com.intellij.util.io.TarUtil
#-libraryjars '<rtjar>'
#-libraryjars '<jssejar>'

View File

@@ -28,8 +28,8 @@ enum class JvmTarget(override val description: String) : TargetPlatformVersion {
JVM_1_6 -> Opcodes.V1_6
JVM_1_8 ->
when {
java.lang.Boolean.valueOf(System.getProperty("kotlin.test.substitute.bytecode.1.8.to.10")) -> Opcodes.V9 + 1
java.lang.Boolean.valueOf(System.getProperty("kotlin.test.substitute.bytecode.1.8.to.1.9")) -> Opcodes.V9
java.lang.Boolean.valueOf(System.getProperty("kotlin.test.substitute.bytecode.1.8.to.10")) -> Opcodes.V1_9 + 1
java.lang.Boolean.valueOf(System.getProperty("kotlin.test.substitute.bytecode.1.8.to.1.9")) -> Opcodes.V1_9
else -> Opcodes.V1_8
}
}

View File

@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ErrorValue
val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
private val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
val JVM_FIELD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmField")

View File

@@ -55,12 +55,6 @@ abstract class KtLightAbstractAnnotation(parent: PsiElement, computeDelegate: ()
override fun getParameterList() = clsDelegate.parameterList
override fun canNavigate(): Boolean = super<KtLightElementBase>.canNavigate()
override fun canNavigateToSource(): Boolean = super<KtLightElementBase>.canNavigateToSource()
override fun navigate(requestFocus: Boolean) = super<KtLightElementBase>.navigate(requestFocus)
open fun fqNameMatches(fqName: String): Boolean = qualifiedName == fqName
}
@@ -319,12 +313,6 @@ class KtLightNonExistentAnnotation(parent: KtLightElement<*, *>) : KtLightElemen
override fun findDeclaredAttributeValue(attributeName: String?) = null
override fun getMetaData() = null
override fun getParameterList() = KtLightEmptyAnnotationParameterList(this)
override fun canNavigate(): Boolean = super<KtLightElementBase>.canNavigate()
override fun canNavigateToSource(): Boolean = super<KtLightElementBase>.canNavigateToSource()
override fun navigate(requestFocus: Boolean) = super<KtLightElementBase>.navigate(requestFocus)
}
class KtLightEmptyAnnotationParameterList(parent: PsiElement) : KtLightElementBase(parent), PsiAnnotationParameterList {

View File

@@ -325,8 +325,6 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
return createProperty(text + " val x").modifierList!!
}
fun createEmptyModifierList() = createModifierList(KtTokens.PRIVATE_KEYWORD).apply { firstChild.delete() }
fun createModifier(modifier: KtModifierKeywordToken): PsiElement {
return createModifierList(modifier.value).getModifier(modifier)!!
}

View File

@@ -1,47 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: a/a.java
package a;
public class a {}
// FILE: a/b.java
package a;
public class b {
public void a_b() {}
}
// FILE: test/a.java
package test;
public class a {}
// FILE: test/d.java
package test;
public class d {
public a.b getB() { return null; }
}
// FILE: b.kt
package test
val x = d().getB()
// FILE: test/c.java
package test;
import a.a;
public class c {
public static a getA() { return null; }
}
// FILE: c.kt
package test
fun foo() {
val a = c.getA()
a.<!UNRESOLVED_REFERENCE!>a<!>
a.<!UNRESOLVED_REFERENCE!>a<!>()
}

View File

@@ -139,8 +139,18 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
}
var exceptionFromDescriptorValidation: Throwable? = null
val originalTestFile = testDataFile.readText()
try {
val expectedFile = getExpectedDescriptorFile(testDataFile, files)
val postfix = when {
InTextDirectivesUtils.isDirectiveDefined(originalTestFile, "// JAVAC_EXPECTED_FILE") &&
environment.configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC) -> ".javac.txt"
InTextDirectivesUtils.isDirectiveDefined(originalTestFile, "// NI_EXPECTED_FILE") &&
files.any { it.newInferenceEnabled } && !USE_OLD_INFERENCE_DIAGNOSTICS_FOR_NI -> ".ni.txt"
else -> ".txt"
}
val expectedFile = File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + postfix)
validateAndCompareDescriptorWithFile(expectedFile, files, modules)
} catch (e: Throwable) {
exceptionFromDescriptorValidation = e
@@ -175,7 +185,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
exceptionFromDynamicCallDescriptorsValidation = e
}
KotlinTestUtils.assertEqualsToFile(getExpectedDiagnosticsFile(testDataFile), actualText.toString())
KotlinTestUtils.assertEqualsToFile(testDataFile, actualText.toString())
assertTrue("Diagnostics mismatch. See the output above", ok)
@@ -187,26 +197,6 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
performAdditionalChecksAfterDiagnostics(testDataFile, files, groupedByModule, modules, moduleBindings)
}
protected open fun getExpectedDiagnosticsFile(testDataFile: File): File {
return testDataFile
}
protected open fun getExpectedDescriptorFile(testDataFile: File, files: List<TestFile>): File {
val originalTestFileText = testDataFile.readText()
val postfix = when {
InTextDirectivesUtils.isDirectiveDefined(originalTestFileText, "// JAVAC_EXPECTED_FILE") &&
environment.configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC) -> ".javac.txt"
InTextDirectivesUtils.isDirectiveDefined(originalTestFileText, "// NI_EXPECTED_FILE") &&
files.any { it.newInferenceEnabled } && !USE_OLD_INFERENCE_DIAGNOSTICS_FOR_NI -> ".ni.txt"
else -> ".txt"
}
return File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + postfix)
}
protected open fun performAdditionalChecksAfterDiagnostics(
testDataFile: File,
testFiles: List<TestFile>,

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.checkers.javac
import org.jetbrains.kotlin.checkers.AbstractDiagnosticsTest
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class AbstractJavacDiagnosticsTest : AbstractDiagnosticsTest() {
@@ -40,19 +39,5 @@ abstract class AbstractJavacDiagnosticsTest : AbstractDiagnosticsTest() {
super.doTest(path)
}
override fun getExpectedDiagnosticsFile(testDataFile: File): File {
val suffix = if (useJavac) ".WithJavac.txt" else ".WithoutJavac.txt"
val specialFile = File(testDataFile.parent, testDataFile.name + suffix)
return specialFile.takeIf { it.exists() } ?: super.getExpectedDiagnosticsFile(testDataFile)
}
override fun createTestFiles(file: File, expectedText: String, modules: MutableMap<String, ModuleAndDependencies>?): List<TestFile> {
val specialFile = getExpectedDiagnosticsFile(file)
if (file.path == specialFile.path) {
return super.createTestFiles(file, expectedText, modules)
}
return super.createTestFiles(specialFile, KotlinTestUtils.doLoadFile(specialFile), modules)
}
}

View File

@@ -16,8 +16,6 @@
package org.jetbrains.kotlin.test.testFramework
import com.intellij.mock.MockApplication
import com.intellij.openapi.application.ApplicationManager
import org.jetbrains.annotations.TestOnly
import java.lang.reflect.InvocationTargetException
import javax.swing.SwingUtilities
@@ -41,12 +39,7 @@ fun runInEdtAndWait(runnable: () -> Unit) {
}
else {
try {
val application = ApplicationManager.getApplication()
.takeIf { it !is MockApplication } // because MockApplication do nothing instead of `invokeAndWait`
if (application != null)
application.invokeAndWait(runnable)
else
SwingUtilities.invokeAndWait(runnable)
SwingUtilities.invokeAndWait(runnable)
}
catch (e: InvocationTargetException) {
throw e.cause ?: e

View File

@@ -52,7 +52,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public abstract class KtUsefulTestCase extends TestCase {
@@ -218,11 +217,9 @@ public abstract class KtUsefulTestCase extends TestCase {
protected void runTest() throws Throwable {
Throwable[] throwables = new Throwable[1];
AtomicBoolean completed = new AtomicBoolean(false);
Runnable runnable = () -> {
try {
super.runTest();
completed.set(true);
}
catch (InvocationTargetException e) {
e.fillInStackTrace();
@@ -242,9 +239,6 @@ public abstract class KtUsefulTestCase extends TestCase {
if (throwables[0] != null) {
throw throwables[0];
}
if (!completed.get()) {
throw new IllegalStateException("test didn't start");
}
}
private static void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {

View File

@@ -30,15 +30,14 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
public class MockFileManager implements FileManager {
private final PsiManagerEx myManager;
// in mock tests it's LightVirtualFile, they're only alive when they're referenced,
// and there can not be several instances representing the same file
private final ConcurrentMap<VirtualFile, FileViewProvider> myViewProviders = new ConcurrentWeakFactoryMap<VirtualFile, FileViewProvider>() {
private final FactoryMap<VirtualFile, FileViewProvider> myViewProviders = new ConcurrentWeakFactoryMap<VirtualFile, FileViewProvider>() {
@Override
protected ConcurrentMap<VirtualFile, FileViewProvider> createMap() {
protected Map<VirtualFile, FileViewProvider> createMap() {
return ContainerUtil.createConcurrentWeakKeyWeakValueMap();
}

View File

@@ -135,9 +135,7 @@ import org.jetbrains.kotlin.idea.scratch.AbstractScratchRunActionTest
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationCompletionTest
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationHighlightingTest
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationNavigationTest
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerLeafGroupingTest
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerNullnessGroupingTest
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerTreeTest
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerTest
import org.jetbrains.kotlin.idea.structureView.AbstractKotlinFileStructureTest
import org.jetbrains.kotlin.idea.stubs.AbstractMultiFileHighlightingTest
import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest
@@ -749,18 +747,10 @@ fun main(args: Array<String>) {
model("refactoring/nameSuggestionProvider")
}
testClass<AbstractSlicerTreeTest> {
testClass<AbstractSlicerTest> {
model("slicer", singleClass = true)
}
testClass<AbstractSlicerLeafGroupingTest> {
model("slicer/inflow", singleClass = true)
}
testClass<AbstractSlicerNullnessGroupingTest> {
model("slicer/inflow", singleClass = true)
}
testClass<AbstractScratchRunActionTest> {
model("scratch", extension = "kts", testMethod = "doCompilingTest", testClassName = "Compiling", recursive = false)
model("scratch", extension = "kts", testMethod = "doReplTest", testClassName = "Repl", recursive = false)

View File

@@ -85,13 +85,12 @@ public class KotlinCommonCodeStyleSettings extends CommonCodeStyleSettings {
private void writeExternalBase(Element element, CommonCodeStyleSettings defaultSettings) throws WriteExternalException {
Set<String> supportedFields = getSupportedFields();
if (supportedFields != null) {
supportedFields.add("PARENT_SETTINGS_INSTALLED");
supportedFields.add("FORCE_REARRANGE_MODE");
supportedFields.add("CODE_STYLE_DEFAULTS");
}
//noinspection deprecation
DefaultJDOMExternalizer.writeExternal(this, element, new SupportedFieldsDiffFilter(this, supportedFields, defaultSettings));
List<Integer> softMargins = getSoftMargins();
serializeInto(softMargins, element);
IndentOptions myIndentOptions = getIndentOptions();
if (myIndentOptions != null) {
@@ -140,21 +139,6 @@ public class KotlinCommonCodeStyleSettings extends CommonCodeStyleSettings {
commonSettings.setArrangementSettings(arrangementSettings.clone());
}
try {
Method setRootSettingsMethod = ArraysKt.singleOrNull(
CommonCodeStyleSettings.class.getDeclaredMethods(),
method -> "setSoftMargins".equals(method.getName()));
if (setRootSettingsMethod != null) {
// Method was introduced in 173
setRootSettingsMethod.setAccessible(true);
setRootSettingsMethod.invoke(commonSettings, getSoftMargins());
}
}
catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
return commonSettings;
}
@@ -169,9 +153,6 @@ public class KotlinCommonCodeStyleSettings extends CommonCodeStyleSettings {
}
CommonCodeStyleSettings other = (CommonCodeStyleSettings) obj;
if (!getSoftMargins().equals(other.getSoftMargins())) {
return false;
}
IndentOptions options = getIndentOptions();
if ((options == null && other.getIndentOptions() != null) ||
@@ -181,13 +162,6 @@ public class KotlinCommonCodeStyleSettings extends CommonCodeStyleSettings {
return arrangementSettingsEqual(other);
}
// SoftMargins.serializeInfo
private void serializeInto(@NotNull List<Integer> softMargins, @NotNull Element element) {
if (softMargins.size() > 0) {
XmlSerializer.serializeInto(this, element);
}
}
//</editor-fold>
//<editor-fold desc="Copied from CommonCodeStyleSettings">

View File

@@ -33,7 +33,7 @@ class KtLightClassForDecompiledDeclaration(
override val kotlinOrigin: KtClassOrObject?,
private val file: KtClsFile
) : KtLightClassBase(clsDelegate.manager) {
val fqName = kotlinOrigin?.fqName ?: FqName(clsDelegate.qualifiedName.orEmpty())
val fqName = kotlinOrigin?.fqName ?: FqName(clsDelegate.qualifiedName)
override fun copy() = this

View File

@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.addRemoveModifier.MODIFIERS_ORDER
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference
import org.jetbrains.kotlin.resolve.BindingContext
@@ -44,7 +43,6 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.SmartList
@Suppress("UNCHECKED_CAST")
inline fun <reified T : PsiElement> PsiElement.replaced(newElement: T): T {
@@ -449,30 +447,6 @@ fun KtParameter.setDefaultValue(newDefaultValue: KtExpression): PsiElement? {
return addAfter(newDefaultValue, eq) as KtExpression
}
fun KtModifierList.appendModifier(modifier: KtModifierKeywordToken) {
add(KtPsiFactory(this).createModifier(modifier))
}
fun KtModifierList.normalize(): KtModifierList {
val psiFactory = KtPsiFactory(this)
return psiFactory.createEmptyModifierList().also { newList ->
val modifiers = SmartList<PsiElement>()
allChildren.forEach {
val elementType = it.node.elementType
when {
it is KtAnnotation || it is KtAnnotationEntry -> newList.add(it)
elementType is KtModifierKeywordToken -> {
if (elementType == KtTokens.DEFAULT_VISIBILITY_KEYWORD) return@forEach
if (elementType == KtTokens.FINALLY_KEYWORD && !hasModifier(KtTokens.OVERRIDE_KEYWORD)) return@forEach
modifiers.add(it)
}
}
}
modifiers.sortBy { MODIFIERS_ORDER.indexOf(it.node.elementType) }
modifiers.forEach { newList.add(it) }
}
}
fun KtBlockStringTemplateEntry.canDropBraces() =
expression is KtNameReferenceExpression && canPlaceAfterSimpleNameEntry(nextSibling)

View File

@@ -14,14 +14,8 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.slicer
@file:JvmName("GradleKotlinDSLConstants")
import com.intellij.slicer.SliceRootNode
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
package org.jetbrains.kotlin.gradle.kdsl
abstract class AbstractSlicerTreeTest : AbstractSlicerTest() {
override fun doTest(path: String, sliceProvider: KotlinSliceProvider, rootNode: SliceRootNode) {
KotlinTestUtils.assertEqualsToFile(File(path.replace(".kt", ".results.txt")), buildTreeRepresentation(rootNode))
}
}
const val DEFAULT_SCRIPT_NAME = "build.gradle.kts"

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.kotlin.gradle.kdsl.GradleFrameworksWizardStep">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="22e59" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="ad16" binding="myOptionsPanel" layout-manager="CardLayout" hgap="0" vgap="0">
<constraints border-constraint="Center"/>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
<border type="none"/>
<children>
<grid id="27a92" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<card name="templates card"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<grid id="b50ee" binding="myFrameworksPanelPlaceholder" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<card name="frameworks card"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="916d9" class="com.intellij.ui.components.JBLabel" binding="myFrameworksLabel">
<constraints border-constraint="North"/>
<properties>
<text value="Additional Libraries and &amp;Frameworks:"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</children>
</grid>
</children>
</grid>
</form>

View File

@@ -0,0 +1,101 @@
/*
* 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.gradle.kdsl;
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
import com.intellij.ide.util.newProjectWizard.AddSupportForFrameworksPanel;
import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelBase;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleFrameworkSupportProvider;
import org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleJavaFrameworkSupportProvider;
import javax.swing.*;
import java.awt.*;
import java.util.Collections;
import java.util.List;
public class GradleFrameworksWizardStep extends ModuleWizardStep implements Disposable {
private JPanel myPanel;
private final AddSupportForFrameworksPanel myFrameworksPanel;
private JPanel myFrameworksPanelPlaceholder;
private JPanel myOptionsPanel;
@SuppressWarnings("unused") private JBLabel myFrameworksLabel;
public GradleFrameworksWizardStep(WizardContext context, final ModuleBuilder builder) {
Project project = context.getProject();
final LibrariesContainer container = LibrariesContainerFactory.createContainer(context.getProject());
FrameworkSupportModelBase model = new FrameworkSupportModelBase(project, null, container) {
@NotNull
@Override
public String getBaseDirectoryForLibrariesPath() {
return StringUtil.notNullize(builder.getContentEntryPath());
}
};
myFrameworksPanel =
new AddSupportForFrameworksPanel(Collections.emptyList(), model, true, null);
List<FrameworkSupportInModuleProvider> providers = ContainerUtil.newArrayList();
Collections.addAll(providers, GradleFrameworkSupportProvider.EP_NAME.getExtensions());
myFrameworksPanel.setProviders(providers, Collections.emptySet(), Collections.singleton(GradleJavaFrameworkSupportProvider.ID));
Disposer.register(this, myFrameworksPanel);
myFrameworksPanelPlaceholder.add(myFrameworksPanel.getMainPanel());
ModuleBuilder.ModuleConfigurationUpdater configurationUpdater = new ModuleBuilder.ModuleConfigurationUpdater() {
@Override
public void update(@NotNull Module module, @NotNull ModifiableRootModel rootModel) {
myFrameworksPanel.addSupport(module, rootModel);
}
};
builder.addModuleConfigurationUpdater(configurationUpdater);
((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, "frameworks card");
}
@Override
public JComponent getComponent() {
return myPanel;
}
@Override
public void updateDataModel() {
}
@Override
public void dispose() {
}
@Override
public void disposeUIResources() {
Disposer.dispose(this);
}
}

View File

@@ -0,0 +1,491 @@
/*
* 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.gradle.kdsl;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.highlighter.ModuleFileType;
import com.intellij.ide.projectWizard.ProjectSettingsStep;
import com.intellij.ide.util.EditorHelper;
import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.SettingsStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.importing.ImportSpec;
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder;
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.project.ProjectId;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl;
import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalModuleBuilder;
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.module.*;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.containers.ContainerUtil;
import org.gradle.util.GradleVersion;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.BuildScriptDataBuilder;
import org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.KotlinBuildScriptDataBuilder;
import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl;
import org.jetbrains.plugins.gradle.settings.DistributionType;
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import static org.jetbrains.kotlin.gradle.kdsl.GradleKotlinDSLConstants.DEFAULT_SCRIPT_NAME;
public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradleProjectSettings> {
private static final Logger LOG = Logger.getInstance(GradleModuleBuilder.class);
private static final String TEMPLATE_GRADLE_SETTINGS = "Gradle Kotlin DSL Settings.gradle";
private static final String TEMPLATE_GRADLE_SETTINGS_MERGE = "Gradle Settings merge.gradle";
private static final String TEMPLATE_GRADLE_BUILD_WITH_WRAPPER = "Gradle Build Script with wrapper.gradle";
private static final String DEFAULT_TEMPLATE_GRADLE_BUILD = "Gradle Kotlin DSL Build Script.gradle";
private static final String TEMPLATE_ATTRIBUTE_PROJECT_NAME = "PROJECT_NAME";
private static final String TEMPLATE_ATTRIBUTE_MODULE_PATH = "MODULE_PATH";
private static final String TEMPLATE_ATTRIBUTE_MODULE_FLAT_DIR = "MODULE_FLAT_DIR";
private static final String TEMPLATE_ATTRIBUTE_MODULE_NAME = "MODULE_NAME";
private static final String TEMPLATE_ATTRIBUTE_MODULE_GROUP = "MODULE_GROUP";
private static final String TEMPLATE_ATTRIBUTE_MODULE_VERSION = "MODULE_VERSION";
private static final String TEMPLATE_ATTRIBUTE_GRADLE_VERSION = "GRADLE_VERSION";
private static final String TEMPLATE_ATTRIBUTE_BUILD_FILE_NAME = "BUILD_FILE_NAME";
private static final Key<KotlinBuildScriptDataBuilder> BUILD_SCRIPT_DATA =
Key.create("gradle.module.kotlinBuildScriptData");
private WizardContext myWizardContext;
@Nullable
private ProjectData myParentProject;
private boolean myInheritGroupId;
private boolean myInheritVersion;
private ProjectId myProjectId;
private String rootProjectPath;
public GradleModuleBuilder() {
super(GradleConstants.SYSTEM_ID, new GradleProjectSettings());
}
@Override
public String getPresentableName() {
return "Gradle (Kotlin DSL)";
}
@NotNull
@Override
public Module createModule(@NotNull ModifiableModuleModel moduleModel)
throws InvalidDataException, IOException, ModuleWithNameAlreadyExists, JDOMException, ConfigurationException {
LOG.assertTrue(getName() != null);
final String originModuleFilePath = getModuleFilePath();
LOG.assertTrue(originModuleFilePath != null);
String moduleName;
if (myProjectId == null) {
moduleName = getName();
}
else {
moduleName = ModuleGrouperKt.isQualifiedModuleNamesEnabled() && StringUtil.isNotEmpty(myProjectId.getGroupId())
? (myProjectId.getGroupId() + '.' + myProjectId.getArtifactId())
: myProjectId.getArtifactId();
}
Project contextProject = myWizardContext.getProject();
String projectFileDirectory = null;
if (myWizardContext.isCreatingNewProject() || contextProject == null || contextProject.getBasePath() == null) {
projectFileDirectory = myWizardContext.getProjectFileDirectory();
}
else if (myWizardContext.getProjectStorageFormat() == StorageScheme.DEFAULT) {
String moduleFileDirectory = getModuleFileDirectory();
if (moduleFileDirectory != null) {
projectFileDirectory = moduleFileDirectory;
}
}
if (projectFileDirectory == null) {
projectFileDirectory = contextProject.getBasePath();
}
if (myWizardContext.getProjectStorageFormat() == StorageScheme.DIRECTORY_BASED) {
projectFileDirectory += "/.idea/modules";
}
String moduleFilePath = projectFileDirectory + "/" + moduleName + ModuleFileType.DOT_DEFAULT_EXTENSION;
deleteModuleFile(moduleFilePath);
final ModuleType moduleType = getModuleType();
final Module module = moduleModel.newModule(moduleFilePath, moduleType.getId());
setupModule(module);
return module;
}
@Override
public void setupRootModel(final ModifiableRootModel modifiableRootModel) throws ConfigurationException {
String contentEntryPath = getContentEntryPath();
if (StringUtil.isEmpty(contentEntryPath)) {
return;
}
File contentRootDir = new File(contentEntryPath);
FileUtilRt.createDirectory(contentRootDir);
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
VirtualFile modelContentRootDir = fileSystem.refreshAndFindFileByIoFile(contentRootDir);
if (modelContentRootDir == null) {
return;
}
modifiableRootModel.addContentEntry(modelContentRootDir);
// todo this should be moved to generic ModuleBuilder
if (myJdk != null) {
modifiableRootModel.setSdk(myJdk);
}
else {
modifiableRootModel.inheritSdk();
}
final Project project = modifiableRootModel.getProject();
if (myParentProject != null) {
rootProjectPath = myParentProject.getLinkedExternalProjectPath();
}
else {
rootProjectPath =
FileUtil.toCanonicalPath(myWizardContext.isCreatingNewProject() ? project.getBasePath() : modelContentRootDir.getPath());
}
assert rootProjectPath != null;
final VirtualFile gradleBuildFile = setupGradleBuildFile(modelContentRootDir);
setupGradleSettingsFile(
rootProjectPath, modelContentRootDir, modifiableRootModel.getProject().getName(),
myProjectId == null ? modifiableRootModel.getModule().getName() : myProjectId.getArtifactId(),
myWizardContext.isCreatingNewProject() || myParentProject == null
);
if (gradleBuildFile != null) {
modifiableRootModel.getModule().putUserData(
BUILD_SCRIPT_DATA, new KotlinBuildScriptDataBuilder(gradleBuildFile));
}
}
@Override
protected void setupModule(Module module) throws ConfigurationException {
super.setupModule(module);
assert rootProjectPath != null;
VirtualFile buildScriptFile = null;
final BuildScriptDataBuilder buildScriptDataBuilder = getBuildScriptData(module);
try {
if (buildScriptDataBuilder != null) {
buildScriptFile = buildScriptDataBuilder.getBuildScriptFile();
String lineSeparator = lineSeparator(buildScriptFile);
String configurationPart = StringUtil.convertLineSeparators(buildScriptDataBuilder.buildConfigurationPart(), lineSeparator);
String existingText = StringUtil.trimTrailing(VfsUtilCore.loadText(buildScriptFile));
String content = (!configurationPart.isEmpty() ? configurationPart + lineSeparator : "") +
(!existingText.isEmpty() ? existingText + lineSeparator : "") +
lineSeparator +
StringUtil.convertLineSeparators(buildScriptDataBuilder.buildMainPart(), lineSeparator);
VfsUtil.saveText(buildScriptFile, content);
}
}
catch (IOException e) {
LOG.warn("Unexpected exception on applying frameworks templates", e);
}
final Project project = module.getProject();
if (myWizardContext.isCreatingNewProject()) {
getExternalProjectSettings().setExternalProjectPath(rootProjectPath);
AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID);
project.putUserData(ExternalSystemDataKeys.NEWLY_CREATED_PROJECT, Boolean.TRUE);
//noinspection unchecked
settings.linkProject(getExternalProjectSettings());
}
else {
FileDocumentManager.getInstance().saveAllDocuments();
final GradleProjectSettings gradleProjectSettings = getExternalProjectSettings();
final VirtualFile finalBuildScriptFile = buildScriptFile;
Runnable runnable = () -> {
if (myParentProject == null) {
gradleProjectSettings.setExternalProjectPath(rootProjectPath);
AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID);
//noinspection unchecked
settings.linkProject(gradleProjectSettings);
}
ImportSpec importSpec = new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
.use(ProgressExecutionMode.IN_BACKGROUND_ASYNC)
.createDirectoriesForEmptyContentRoots()
.useDefaultCallback()
.build();
ExternalSystemUtil.refreshProject(rootProjectPath, importSpec);
final PsiFile psiFile;
if (finalBuildScriptFile != null) {
psiFile = PsiManager.getInstance(project).findFile(finalBuildScriptFile);
if (psiFile != null) {
EditorHelper.openInEditor(psiFile);
}
}
};
// execute when current dialog is closed
ExternalSystemUtil.invokeLater(project, ModalityState.NON_MODAL, runnable);
}
}
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
myWizardContext = wizardContext;
return new ModuleWizardStep[]{
new GradleModuleWizardStep(this, wizardContext),
new ExternalModuleSettingsStep<>(
wizardContext, this, new GradleProjectSettingsControl(getExternalProjectSettings()))
};
}
@Nullable
@Override
public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
final GradleFrameworksWizardStep step = new GradleFrameworksWizardStep(context, this);
Disposer.register(parentDisposable, step);
return step;
}
@Override
public boolean isSuitableSdkType(SdkTypeId sdk) {
return sdk instanceof JavaSdkType;
}
@Override
public String getParentGroup() {
return JavaModuleType.BUILD_TOOLS_GROUP;
}
@Override
public int getWeight() {
return JavaModuleBuilder.BUILD_SYSTEM_WEIGHT;
}
@Override
public ModuleType getModuleType() {
return StdModuleTypes.JAVA;
}
@Nullable
private VirtualFile setupGradleBuildFile(@NotNull VirtualFile modelContentRootDir)
throws ConfigurationException {
final VirtualFile file = getOrCreateExternalProjectConfigFile(modelContentRootDir.getPath(), GradleKotlinDSLConstants.DEFAULT_SCRIPT_NAME);
if (file != null) {
final String templateName = getExternalProjectSettings().getDistributionType() == DistributionType.WRAPPED
? TEMPLATE_GRADLE_BUILD_WITH_WRAPPER
: DEFAULT_TEMPLATE_GRADLE_BUILD;
Map<String, String> attributes = ContainerUtil.newHashMap();
if (myProjectId != null) {
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_VERSION, myProjectId.getVersion());
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_GROUP, myProjectId.getGroupId());
attributes.put(TEMPLATE_ATTRIBUTE_GRADLE_VERSION, GradleVersion.current().getVersion());
}
saveFile(file, templateName, attributes);
}
return file;
}
@Nullable
public static VirtualFile setupGradleSettingsFile(@NotNull String rootProjectPath,
@NotNull VirtualFile modelContentRootDir,
String projectName,
String moduleName,
boolean renderNewFile)
throws ConfigurationException {
final VirtualFile file = getOrCreateExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME);
if (file == null) return null;
if (renderNewFile) {
final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, file.getParent(), '/');
Map<String, String> attributes = ContainerUtil.newHashMap();
attributes.put(TEMPLATE_ATTRIBUTE_PROJECT_NAME, projectName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, moduleDirName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, moduleName);
attributes.put(TEMPLATE_ATTRIBUTE_BUILD_FILE_NAME, DEFAULT_SCRIPT_NAME); // TODO: gradle > 4.0 doesn't need this
saveFile(file, TEMPLATE_GRADLE_SETTINGS, attributes);
}
else {
char separatorChar = file.getParent() == null || !VfsUtilCore.isAncestor(file.getParent(), modelContentRootDir, true) ? '/' : ':';
String modulePath = VfsUtil.getPath(file, modelContentRootDir, separatorChar);
Map<String, String> attributes = ContainerUtil.newHashMap();
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, moduleName);
// check for flat structure
final String flatStructureModulePath =
modulePath != null && StringUtil.startsWith(modulePath, "../") ? StringUtil.trimStart(modulePath, "../") : null;
if (StringUtil.equals(flatStructureModulePath, modelContentRootDir.getName())) {
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_FLAT_DIR, "true");
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, flatStructureModulePath);
}
else {
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, modulePath);
}
appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes);
}
return file;
}
private static void saveFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
throws ConfigurationException {
FileTemplateManager manager = FileTemplateManager.getDefaultInstance();
FileTemplate template = manager.getInternalTemplate(templateName);
try {
appendToFile(file, templateAttributes != null ? template.getText(templateAttributes) : template.getText());
}
catch (IOException e) {
LOG.warn(String.format("Unexpected exception on applying template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
throw new ConfigurationException(
e.getMessage(), String.format("Can't apply %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
);
}
}
private static void appendToFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
throws ConfigurationException {
FileTemplateManager manager = FileTemplateManager.getDefaultInstance();
FileTemplate template = manager.getInternalTemplate(templateName);
try {
appendToFile(file, templateAttributes != null ? template.getText(templateAttributes) : template.getText());
}
catch (IOException e) {
LOG.warn(String.format("Unexpected exception on appending template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
throw new ConfigurationException(
e.getMessage(), String.format("Can't append %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
);
}
}
@Nullable
private static VirtualFile getOrCreateExternalProjectConfigFile(@NotNull String parent, @NotNull String fileName) {
File file = new File(parent, fileName);
FileUtilRt.createIfNotExists(file);
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
}
public void setParentProject(@Nullable ProjectData parentProject) {
myParentProject = parentProject;
}
public boolean isInheritGroupId() {
return myInheritGroupId;
}
public void setInheritGroupId(boolean inheritGroupId) {
myInheritGroupId = inheritGroupId;
}
public boolean isInheritVersion() {
return myInheritVersion;
}
public void setInheritVersion(boolean inheritVersion) {
myInheritVersion = inheritVersion;
}
public ProjectId getProjectId() {
return myProjectId;
}
public void setProjectId(@NotNull ProjectId projectId) {
myProjectId = projectId;
}
@Nullable
@Override
public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep) {
if (settingsStep instanceof ProjectSettingsStep) {
final ProjectSettingsStep projectSettingsStep = (ProjectSettingsStep)settingsStep;
if (myProjectId != null) {
final JTextField moduleNameField = settingsStep.getModuleNameField();
if (moduleNameField != null) {
moduleNameField.setText(myProjectId.getArtifactId());
}
projectSettingsStep.setModuleName(myProjectId.getArtifactId());
}
projectSettingsStep.bindModuleSettings();
}
return super.modifySettingsStep(settingsStep);
}
public static void appendToFile(@NotNull VirtualFile file, @NotNull String text) throws IOException {
String lineSeparator = lineSeparator(file);
final String existingText = StringUtil.trimTrailing(VfsUtilCore.loadText(file));
String content = (StringUtil.isNotEmpty(existingText) ? existingText + lineSeparator : "") +
StringUtil.convertLineSeparators(text, lineSeparator);
VfsUtil.saveText(file, content);
}
@NotNull
private static String lineSeparator(@NotNull VirtualFile file) {
String lineSeparator = LoadTextUtil.detectLineSeparator(file, true);
if (lineSeparator == null) {
lineSeparator = CodeStyleSettingsManager.getSettings(ProjectManagerEx.getInstanceEx().getDefaultProject()).getLineSeparator();
}
return lineSeparator;
}
@Nullable
public static BuildScriptDataBuilder getBuildScriptData(@Nullable Module module) {
return module == null ? null : module.getUserData(BUILD_SCRIPT_DATA);
}
@Nullable
@Override
public Project createProject(String name, String path) {
Project project = super.createProject(name, path);
if (project != null) {
GradleProjectSettings settings = getExternalProjectSettings();
ExternalProjectsManagerImpl.getInstance(project).setStoreExternally(settings.isStoreProjectFilesExternally());
}
return project;
}
}

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.kotlin.gradle.kdsl.GradleModuleWizardStep">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="5" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="529" height="386"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="ddae6" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="d7d25"/>
<text value="GroupId"/>
</properties>
</component>
<component id="bbb74" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="efb5e"/>
<text value="ArtifactId"/>
</properties>
</component>
<component id="4eb56" class="javax.swing.JLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="b1344"/>
<text value="Version"/>
</properties>
</component>
<component id="d7d25" class="javax.swing.JTextField" binding="myGroupIdField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="efb5e" class="javax.swing.JTextField" binding="myArtifactIdField">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="b1344" class="javax.swing.JTextField" binding="myVersionField">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="d0095" class="javax.swing.JCheckBox" binding="myInheritGroupIdCheckBox">
<constraints>
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Inherit"/>
</properties>
</component>
<component id="897ff" class="javax.swing.JCheckBox" binding="myInheritVersionCheckBox">
<constraints>
<grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Inherit"/>
</properties>
</component>
<grid id="102d8" binding="myAddToPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<grid id="90185" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<enabled value="true"/>
</properties>
<border type="none"/>
<children>
<vspacer id="f04b8">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</children>
</grid>
</form>

View File

@@ -0,0 +1,257 @@
/*
* 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.gradle.kdsl;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.project.ProjectId;
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.service.project.wizard.GradleParentProjectForm;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GradleModuleWizardStep extends ModuleWizardStep {
private static final Icon WIZARD_ICON = null;
private static final String INHERIT_GROUP_ID_KEY = "GradleModuleWizard.inheritGroupId";
private static final String INHERIT_VERSION_KEY = "GradleModuleWizard.inheritVersion";
private static final String DEFAULT_VERSION = "1.0-SNAPSHOT";
@Nullable
private final Project myProjectOrNull;
@NotNull
private final GradleModuleBuilder myBuilder;
@NotNull
private final WizardContext myContext;
@NotNull
private final GradleParentProjectForm myParentProjectForm;
private String myInheritedGroupId;
private String myInheritedVersion;
private JPanel myMainPanel;
private JTextField myGroupIdField;
private JCheckBox myInheritGroupIdCheckBox;
private JTextField myArtifactIdField;
private JTextField myVersionField;
private JCheckBox myInheritVersionCheckBox;
private JPanel myAddToPanel;
public GradleModuleWizardStep(@NotNull GradleModuleBuilder builder, @NotNull WizardContext context) {
myProjectOrNull = context.getProject();
myBuilder = builder;
myContext = context;
myParentProjectForm = new GradleParentProjectForm(context, parentProject -> updateComponents());
initComponents();
loadSettings();
}
private void initComponents() {
myAddToPanel.add(myParentProjectForm.getComponent());
ActionListener updatingListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateComponents();
}
};
myInheritGroupIdCheckBox.addActionListener(updatingListener);
myInheritVersionCheckBox.addActionListener(updatingListener);
}
@Override
public JComponent getPreferredFocusedComponent() {
return myGroupIdField;
}
@Override
public void onStepLeaving() {
saveSettings();
}
private void loadSettings() {
myBuilder.setInheritGroupId(getSavedValue(INHERIT_GROUP_ID_KEY, true));
myBuilder.setInheritVersion(getSavedValue(INHERIT_VERSION_KEY, true));
}
private void saveSettings() {
saveValue(INHERIT_GROUP_ID_KEY, myInheritGroupIdCheckBox.isSelected());
saveValue(INHERIT_VERSION_KEY, myInheritVersionCheckBox.isSelected());
}
private static boolean getSavedValue(String key, boolean defaultValue) {
return getSavedValue(key, String.valueOf(defaultValue)).equals(String.valueOf(true));
}
private static String getSavedValue(String key, String defaultValue) {
String value = PropertiesComponent.getInstance().getValue(key);
return value == null ? defaultValue : value;
}
private static void saveValue(String key, boolean value) {
saveValue(key, String.valueOf(value));
}
private static void saveValue(String key, String value) {
PropertiesComponent.getInstance().setValue(key, value);
}
public JComponent getComponent() {
return myMainPanel;
}
@Override
public boolean validate() throws ConfigurationException {
if (StringUtil.isEmptyOrSpaces(myArtifactIdField.getText())) {
ApplicationManager.getApplication().invokeLater(
() -> IdeFocusManager.getInstance(myProjectOrNull).requestFocus(myArtifactIdField, true));
throw new ConfigurationException("Please, specify artifactId");
}
return true;
}
@Override
public void updateStep() {
ProjectData parentProject = myParentProjectForm.getParentProject();
ProjectId projectId = myBuilder.getProjectId();
if (projectId == null) {
setTestIfEmpty(myArtifactIdField, myBuilder.getName());
setTestIfEmpty(myGroupIdField, parentProject == null ? myBuilder.getName() : parentProject.getGroup());
setTestIfEmpty(myVersionField, parentProject == null ? DEFAULT_VERSION : parentProject.getVersion());
}
else {
setTestIfEmpty(myArtifactIdField, projectId.getArtifactId());
setTestIfEmpty(myGroupIdField, projectId.getGroupId());
setTestIfEmpty(myVersionField, projectId.getVersion());
}
myInheritGroupIdCheckBox.setSelected(myBuilder.isInheritGroupId());
myInheritVersionCheckBox.setSelected(myBuilder.isInheritVersion());
updateComponents();
}
private void updateComponents() {
final boolean isAddToVisible = myParentProjectForm.isVisible();
myInheritGroupIdCheckBox.setVisible(isAddToVisible);
myInheritVersionCheckBox.setVisible(isAddToVisible);
myParentProjectForm.updateComponents();
ProjectData parentProject = myParentProjectForm.getParentProject();
if (parentProject == null) {
myContext.putUserData(ExternalModuleSettingsStep.SKIP_STEP_KEY, Boolean.FALSE);
myGroupIdField.setEnabled(true);
myVersionField.setEnabled(true);
myInheritGroupIdCheckBox.setEnabled(false);
myInheritVersionCheckBox.setEnabled(false);
setTestIfEmpty(myArtifactIdField, myBuilder.getName());
setTestIfEmpty(myGroupIdField, "");
setTestIfEmpty(myVersionField, DEFAULT_VERSION);
}
else {
myContext.putUserData(ExternalModuleSettingsStep.SKIP_STEP_KEY, Boolean.TRUE);
myGroupIdField.setEnabled(!myInheritGroupIdCheckBox.isSelected());
myVersionField.setEnabled(!myInheritVersionCheckBox.isSelected());
if (myInheritGroupIdCheckBox.isSelected()
|| myGroupIdField.getText().equals(myInheritedGroupId)) {
myGroupIdField.setText(parentProject.getGroup());
}
if (myInheritVersionCheckBox.isSelected()
|| myVersionField.getText().equals(myInheritedVersion)) {
myVersionField.setText(parentProject.getVersion());
}
myInheritedGroupId = myGroupIdField.getText();
myInheritedVersion = myVersionField.getText();
myInheritGroupIdCheckBox.setEnabled(true);
myInheritVersionCheckBox.setEnabled(true);
}
}
public static boolean isGradleModuleExist(WizardContext myContext) {
for (Module module : myContext.getModulesProvider().getModules()) {
if (ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return true;
}
return false;
}
@Override
public void updateDataModel() {
myContext.setProjectBuilder(myBuilder);
ProjectData parentProject = myParentProjectForm.getParentProject();
myBuilder.setParentProject(parentProject);
myBuilder.setProjectId(new ProjectId(myGroupIdField.getText(),
myArtifactIdField.getText(),
myVersionField.getText()));
myBuilder.setInheritGroupId(myInheritGroupIdCheckBox.isSelected());
myBuilder.setInheritVersion(myInheritVersionCheckBox.isSelected());
if (StringUtil.isNotEmpty(myBuilder.getProjectId().getArtifactId())) {
myContext.setProjectName(myBuilder.getProjectId().getArtifactId());
}
if (parentProject != null) {
myContext.setProjectFileDirectory(parentProject.getLinkedExternalProjectPath() + '/' + myContext.getProjectName());
}
else {
if (myProjectOrNull != null) {
myContext.setProjectFileDirectory(myProjectOrNull.getBaseDir().getPath() + '/' + myContext.getProjectName());
}
}
}
@Override
public Icon getIcon() {
return WIZARD_ICON;
}
private static void setTestIfEmpty(@NotNull JTextField field, @Nullable String text) {
if (StringUtil.isEmpty(field.getText())) {
field.setText(StringUtil.notNullize(text));
}
}
@Override
public String getHelpId() {
return "Gradle_Archetype_Dialog";
}
@Override
public void disposeUIResources() {
Disposer.dispose(myParentProjectForm);
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright 2000-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.gradle.kdsl.frameworkSupport;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
public class BuildScriptDataBuilder {
@NotNull private final VirtualFile myBuildScriptFile;
private final Set<String> plugins = ContainerUtil.newTreeSet();
private final Set<String> pluginsInGroup = ContainerUtil.newTreeSet();
private final Set<String> repositories = ContainerUtil.newTreeSet();
private final Set<String> dependencies = ContainerUtil.newTreeSet();
private final Set<String> properties = ContainerUtil.newTreeSet();
private final Set<String> buildScriptProperties = ContainerUtil.newTreeSet();
private final Set<String> buildScriptRepositories = ContainerUtil.newTreeSet();
private final Set<String> buildScriptDependencies = ContainerUtil.newTreeSet();
private final Set<String> other = ContainerUtil.newTreeSet();
public BuildScriptDataBuilder(@NotNull VirtualFile buildScriptFile) {
myBuildScriptFile = buildScriptFile;
}
@NotNull
public VirtualFile getBuildScriptFile() {
return myBuildScriptFile;
}
public String buildConfigurationPart() {
List<String> lines = ContainerUtil.newArrayList();
addBuildscriptLines(lines, BuildScriptDataBuilder::padding);
if (!pluginsInGroup.isEmpty()) {
lines.add("plugins {");
lines.addAll(ContainerUtil.map(pluginsInGroup, BuildScriptDataBuilder::padding));
lines.add("}");
lines.add("");
}
return StringUtil.join(lines, "\n");
}
public String buildMainPart() {
List<String> lines = ContainerUtil.newArrayList();
if (!plugins.isEmpty()) {
lines.addAll(plugins);
lines.add("");
}
if (!properties.isEmpty()) {
lines.addAll(properties);
lines.add("");
}
if (!repositories.isEmpty()) {
lines.add("repositories {");
lines.addAll(ContainerUtil.map(repositories, BuildScriptDataBuilder::padding));
lines.add("}");
lines.add("");
}
if (!dependencies.isEmpty()) {
lines.add("dependencies {");
lines.addAll(ContainerUtil.map(dependencies, BuildScriptDataBuilder::padding));
lines.add("}");
lines.add("");
}
if (!other.isEmpty()) {
lines.addAll(other);
}
return StringUtil.join(lines, "\n");
}
private void addBuildscriptLines(@NotNull List<String> lines, @NotNull Function<String, String> padding) {
if (!buildScriptRepositories.isEmpty() || !buildScriptDependencies.isEmpty() || !buildScriptProperties.isEmpty()) {
lines.add("buildscript {");
final List<String> buildScriptLines = ContainerUtil.newSmartList();
if (!buildScriptProperties.isEmpty()) {
buildScriptLines.addAll(buildScriptProperties);
buildScriptLines.add("");
}
if (!buildScriptRepositories.isEmpty()) {
buildScriptLines.add("repositories {");
buildScriptLines.addAll(ContainerUtil.map(buildScriptRepositories, padding));
buildScriptLines.add("}");
}
if (!buildScriptDependencies.isEmpty()) {
buildScriptLines.add("dependencies {");
buildScriptLines.addAll(ContainerUtil.map(buildScriptDependencies, padding));
buildScriptLines.add("}");
}
lines.addAll(ContainerUtil.map(buildScriptLines, padding));
lines.add("}");
lines.add("");
}
}
public BuildScriptDataBuilder addBuildscriptPropertyDefinition(@NotNull String definition) {
buildScriptProperties.add(definition.trim());
return this;
}
public BuildScriptDataBuilder addBuildscriptRepositoriesDefinition(@NotNull String definition) {
buildScriptRepositories.add(definition.trim());
return this;
}
public BuildScriptDataBuilder addBuildscriptDependencyNotation(@NotNull String notation) {
buildScriptDependencies.add(notation.trim());
return this;
}
public BuildScriptDataBuilder addPluginDefinitionInPluginsGroup(@NotNull String definition) {
pluginsInGroup.add(definition.trim());
return this;
}
public BuildScriptDataBuilder addPluginDefinition(@NotNull String definition) {
plugins.add(definition.trim());
return this;
}
public BuildScriptDataBuilder addRepositoriesDefinition(@NotNull String definition) {
repositories.add(definition.trim());
return this;
}
public BuildScriptDataBuilder addDependencyNotation(@NotNull String notation) {
dependencies.add(notation.trim());
return this;
}
public BuildScriptDataBuilder addPropertyDefinition(@NotNull String definition) {
properties.add(definition.trim());
return this;
}
public BuildScriptDataBuilder addOther(@NotNull String definition) {
other.add(definition.trim());
return this;
}
private static String padding(String s) {return StringUtil.isNotEmpty(s) ? " " + s : "";}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.gradle.kdsl.frameworkSupport;
import com.intellij.framework.addSupport.FrameworkSupportInModuleConfigurable;
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.roots.ModifiableModelsProvider;
import com.intellij.openapi.roots.ModifiableRootModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import static org.jetbrains.kotlin.gradle.kdsl.GradleModuleBuilder.getBuildScriptData;
public abstract class GradleFrameworkSupportProvider extends FrameworkSupportInModuleProvider {
public static final ExtensionPointName<GradleFrameworkSupportProvider> EP_NAME =
ExtensionPointName.create("org.jetbrains.kotlin.gradleFrameworkSupport");
public abstract void addSupport(@NotNull Module module, @NotNull ModifiableRootModel rootModel,
@NotNull ModifiableModelsProvider modifiableModelsProvider,
@NotNull BuildScriptDataBuilder buildScriptData);
public JComponent createComponent() {
return null;
}
@NotNull
@Override
public FrameworkSupportInModuleConfigurable createConfigurable(@NotNull FrameworkSupportModel model) {
return new FrameworkSupportInModuleConfigurable() {
@Nullable
@Override
public JComponent createComponent() {
return GradleFrameworkSupportProvider.this.createComponent();
}
@Override
public void addSupport(@NotNull Module module,
@NotNull ModifiableRootModel rootModel,
@NotNull ModifiableModelsProvider modifiableModelsProvider) {
final BuildScriptDataBuilder buildScriptData = getBuildScriptData(module);
if (buildScriptData != null) {
GradleFrameworkSupportProvider.this.addSupport(module, rootModel, modifiableModelsProvider, buildScriptData);
}
}
};
}
@Override
public boolean isEnabledForModuleType(@NotNull ModuleType moduleType) {
return false;
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.gradle.kdsl.frameworkSupport;
import com.intellij.framework.FrameworkTypeEx;
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableModelsProvider;
import com.intellij.openapi.roots.ModifiableRootModel;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class GradleGroovyFrameworkSupportProvider extends GradleFrameworkSupportProvider {
public static final String ID = "groovy";
@NotNull
@Override
public FrameworkTypeEx getFrameworkType() {
return new FrameworkTypeEx(ID) {
@NotNull
@Override
public FrameworkSupportInModuleProvider createProvider() {
return GradleGroovyFrameworkSupportProvider.this;
}
@NotNull
@Override
public String getPresentableName() {
return "Groovy";
}
@NotNull
@Override
public Icon getIcon() {
return JetgroovyIcons.Groovy.Groovy_16x16;
}
};
}
@Override
public void addSupport(@NotNull Module module,
@NotNull ModifiableRootModel rootModel,
@NotNull ModifiableModelsProvider modifiableModelsProvider,
@NotNull BuildScriptDataBuilder buildScriptData) {
buildScriptData
.addPluginDefinition("plugin(\"groovy\")")
.addRepositoriesDefinition("mavenCentral()")
.addDependencyNotation("compile(\"org.codehaus.groovy:groovy-all:2.3.11\")")
.addDependencyNotation("testCompile(\"junit\", \"junit\", \"4.12\")");
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2000-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.gradle.kdsl.frameworkSupport;
import com.intellij.framework.FrameworkTypeEx;
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableModelsProvider;
import com.intellij.openapi.roots.ModifiableRootModel;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class GradleJavaFrameworkSupportProvider extends GradleFrameworkSupportProvider {
public static final String ID = "java";
@NotNull
@Override
public FrameworkTypeEx getFrameworkType() {
return new FrameworkTypeEx(ID) {
@NotNull
@Override
public FrameworkSupportInModuleProvider createProvider() {
return GradleJavaFrameworkSupportProvider.this;
}
@NotNull
@Override
public String getPresentableName() {
return "Java";
}
@NotNull
@Override
public Icon getIcon() {
return AllIcons.Nodes.Module;
}
};
}
@Override
public void addSupport(@NotNull Module module,
@NotNull ModifiableRootModel rootModel,
@NotNull ModifiableModelsProvider modifiableModelsProvider,
@NotNull BuildScriptDataBuilder buildScriptData) {
buildScriptData
.addPluginDefinition("plugin(\"java\")")
// TODO: in gradle > 4.0 it is just 'java { ... }'
.addOther("configure<JavaPluginConvention> {\n sourceCompatibility = JavaVersion.VERSION_1_8\n}")
.addRepositoriesDefinition("mavenCentral()")
.addDependencyNotation("testCompile(\"junit\", \"junit\", \"4.12\")");
}
}

View File

@@ -14,36 +14,34 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.configuration
package org.jetbrains.kotlin.gradle.kdsl.frameworkSupport
import com.intellij.framework.FrameworkTypeEx
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider
import com.intellij.openapi.externalSystem.model.project.ProjectId
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ModifiableModelsProvider
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.idea.configuration.*
import org.jetbrains.kotlin.idea.configuration.KotlinBuildScriptManipulator.Companion.GSK_KOTLIN_VERSION_PROPERTY_NAME
import org.jetbrains.kotlin.idea.configuration.KotlinBuildScriptManipulator.Companion.getCompileDependencySnippet
import org.jetbrains.kotlin.idea.configuration.KotlinBuildScriptManipulator.Companion.getKotlinGradlePluginClassPathSnippet
import org.jetbrains.kotlin.idea.versions.*
import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder
import org.jetbrains.plugins.gradle.frameworkSupport.KotlinDslGradleFrameworkSupportProvider
import javax.swing.Icon
abstract class KotlinDslGradleKotlinFrameworkSupportProvider(
abstract class GradleKotlinDSLKotlinFrameworkSupportProvider(
val frameworkTypeId: String,
val displayName: String,
val frameworkIcon: Icon
) : KotlinDslGradleFrameworkSupportProvider() {
) : GradleFrameworkSupportProvider() {
override fun getFrameworkType(): FrameworkTypeEx = object : FrameworkTypeEx(frameworkTypeId) {
override fun getIcon(): Icon = frameworkIcon
override fun getPresentableName(): String = displayName
override fun createProvider(): FrameworkSupportInModuleProvider = this@KotlinDslGradleKotlinFrameworkSupportProvider
override fun createProvider(): FrameworkSupportInModuleProvider = this@GradleKotlinDSLKotlinFrameworkSupportProvider
}
override fun addSupport(
projectId: ProjectId,
module: Module,
rootModel: ModifiableRootModel,
modifiableModelsProvider: ModifiableModelsProvider,
@@ -68,20 +66,18 @@ abstract class KotlinDslGradleKotlinFrameworkSupportProvider(
.addBuildscriptRepositoriesDefinition("mavenCentral()")
.addRepositoriesDefinition("mavenCentral()")
// TODO: in gradle > 4.1 this could be single declaration e.g. 'val kotlin_version: String by extra { "1.1.11" }'
.addBuildscriptPropertyDefinition("var $GSK_KOTLIN_VERSION_PROPERTY_NAME: String by extra\n $GSK_KOTLIN_VERSION_PROPERTY_NAME = \"$kotlinVersion\"")
.addBuildscriptPropertyDefinition("var $GSK_KOTLIN_VERSION_PROPERTY_NAME: String by extra\n$GSK_KOTLIN_VERSION_PROPERTY_NAME = \"$kotlinVersion\"")
.addDependencyNotation(getRuntimeLibrary(rootModel))
.addBuildscriptDependencyNotation(getKotlinGradlePluginClassPathSnippet())
}
private fun RepositoryDescription.toKotlinRepositorySnippet() = "maven { setUrl(\"$url\") }"
protected abstract fun getRuntimeLibrary(rootModel: ModifiableRootModel): String
protected abstract fun getPluginDefinition(): String
}
class KotlinDslGradleKotlinJavaFrameworkSupportProvider :
KotlinDslGradleKotlinFrameworkSupportProvider("KOTLIN", "Kotlin (Java)", KotlinIcons.SMALL_LOGO) {
class GradleKotlinDSLKotlinJavaFrameworkSupportProvider :
GradleKotlinDSLKotlinFrameworkSupportProvider("KOTLIN", "Kotlin (Java)", KotlinIcons.SMALL_LOGO) {
override fun getPluginDefinition() = "plugin(\"${KotlinGradleModuleConfigurator.KOTLIN}\")"
@@ -89,24 +85,28 @@ class KotlinDslGradleKotlinJavaFrameworkSupportProvider :
getCompileDependencySnippet(KOTLIN_GROUP_ID, getStdlibArtifactId(rootModel.sdk, bundledRuntimeVersion()))
override fun addSupport(
projectId: ProjectId,
module: Module,
rootModel: ModifiableRootModel,
modifiableModelsProvider: ModifiableModelsProvider,
buildScriptData: BuildScriptDataBuilder
) {
super.addSupport(projectId, module, rootModel, modifiableModelsProvider, buildScriptData)
super.addSupport(module, rootModel, modifiableModelsProvider, buildScriptData)
val jvmTarget = getDefaultJvmTarget(rootModel.sdk, bundledRuntimeVersion())
if (jvmTarget != null) {
buildScriptData
.addImport("import org.jetbrains.kotlin.gradle.tasks.KotlinCompile")
.addImports("import org.jetbrains.kotlin.gradle.tasks.KotlinCompile")
.addOther("tasks.withType<KotlinCompile> {\n kotlinOptions.jvmTarget = \"1.8\"\n}\n")
}
}
private fun BuildScriptDataBuilder.addImports(vararg import: String): BuildScriptDataBuilder = apply {
val text = VfsUtil.loadText(buildScriptFile)
VfsUtil.saveText(buildScriptFile, import.joinToString(separator = "\n") + "\n\n" + text)
}
}
class KotlinDslGradleKotlinJSFrameworkSupportProvider :
KotlinDslGradleKotlinFrameworkSupportProvider("KOTLIN_JS", "Kotlin (JavaScript)", KotlinIcons.JS) {
class GradleKotlinDSLKotlinJSFrameworkSupportProvider :
GradleKotlinDSLKotlinFrameworkSupportProvider("KOTLIN_JS", "Kotlin (JavaScript)", KotlinIcons.JS) {
override fun getPluginDefinition(): String = "plugin(\"${KotlinJsGradleModuleConfigurator.KOTLIN_JS}\")"

View File

@@ -0,0 +1,93 @@
/*
* 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.gradle.kdsl.frameworkSupport
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.containers.ContainerUtil
class KotlinBuildScriptDataBuilder(buildScriptFile: VirtualFile) : BuildScriptDataBuilder(buildScriptFile) {
private val plugins: MutableSet<String> = ContainerUtil.newTreeSet<String>()
private val properties: MutableSet<String> = ContainerUtil.newTreeSet<String>()
private val repositories: MutableSet<String> = ContainerUtil.newTreeSet<String>()
private val dependencies: MutableSet<String> = ContainerUtil.newTreeSet<String>()
private val buildScriptProperties: MutableSet<String> = ContainerUtil.newTreeSet<String>()
private val buildScriptRepositories: MutableSet<String> = ContainerUtil.newTreeSet<String>()
private val buildScriptDependencies: MutableSet<String> = ContainerUtil.newTreeSet<String>()
private val other: MutableSet<String> = ContainerUtil.newTreeSet<String>()
override fun addPluginDefinition(definition: String): BuildScriptDataBuilder = apply { plugins.add(definition) }
override fun addRepositoriesDefinition(definition: String): BuildScriptDataBuilder = apply { repositories.add(definition) }
override fun addPropertyDefinition(definition: String): BuildScriptDataBuilder = apply { properties.add(definition) }
override fun addDependencyNotation(notation: String): BuildScriptDataBuilder = apply { dependencies.add(notation) }
override fun addBuildscriptPropertyDefinition(definition: String): BuildScriptDataBuilder = apply { buildScriptProperties.add(definition) }
override fun addBuildscriptRepositoriesDefinition(definition: String): BuildScriptDataBuilder = apply { buildScriptRepositories.add(definition) }
override fun addBuildscriptDependencyNotation(notation: String): BuildScriptDataBuilder = apply { buildScriptDependencies.add(notation) }
override fun addOther(definition: String): BuildScriptDataBuilder = apply { other.add(definition) }
override fun buildMainPart(): String = buildString {
appendlnIfNotNull(buildBuildScriptBlock())
appendlnIfNotNull(buildBlock("apply", plugins))
if (properties.isNotEmpty()) {
properties.forEach { appendln(it) }
appendln()
}
appendlnIfNotNull(buildBlock("repositories", repositories))
appendlnIfNotNull(buildBlock("dependencies", dependencies))
other.forEach { appendln(it) }
}
private fun buildBuildScriptBlock(): String? = buildString {
if (buildScriptProperties.isEmpty() || buildScriptRepositories.isEmpty() || buildScriptDependencies.isEmpty()) {
return null
}
appendln("buildscript {")
buildScriptProperties.forEach { appendln(it.withMargin) }
appendln()
appendlnIfNotNull(buildBlock("repositories", buildScriptRepositories)?.withMargin)
appendlnIfNotNull(buildBlock("dependencies", buildScriptDependencies)?.withMargin)
appendln("}")
}
private fun buildBlock(name: String, lines: Set<String>): String? = buildString {
if (lines.isEmpty()) {
return null
}
appendln("$name {")
lines.forEach { appendln(it.withMargin) }
appendln("}")
}
private val String.withMargin: String
get() = lines().joinToString(separator = "\n") { " " + it }
private fun StringBuilder.appendlnIfNotNull(text: String?) = text?.let { appendln(it) }
}

View File

@@ -103,7 +103,7 @@ class KotlinGradleMultiplatformModuleBuilder : GradleModuleBuilder() {
val buildGradle = moduleDir.createChildData(null, "build.gradle")
val buildScriptData = BuildScriptDataBuilder(buildGradle)
extendScript(buildScriptData, sdk ?: rootModule.rootManager.sdk)
VfsUtil.saveText(buildGradle, buildScriptData.buildConfigurationPart() + buildScriptData.buildMainPart())
VfsUtil.saveText(buildGradle, buildScriptData.build())
}
private fun setupCommonModule(

View File

@@ -236,10 +236,10 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
override val dependencyResolver: DependenciesResolver = ErrorScriptDependenciesResolver(message)
override fun getScriptName(script: KtScript) =
Name.identifier(script.containingKtFile.name.removeSuffix(GradleConstants.KOTLIN_DSL_SCRIPT_EXTENSION))
Name.identifier(script.containingKtFile.name.removeSuffix(".gradle.kts"))
override fun isScript(fileName: String): Boolean =
fileName.endsWith(GradleConstants.KOTLIN_DSL_SCRIPT_EXTENSION)
fileName.endsWith(".gradle.kts")
}
private class ErrorScriptDependenciesResolver(private val message: String? = null) : DependenciesResolver {

View File

@@ -350,6 +350,7 @@ class GradleInspectionTest : GradleImportingTestCase() {
val foundProblems = presentation.problemElements
.values
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
.map { it.descriptionTemplate }

View File

@@ -54,7 +54,6 @@ import org.jetbrains.kotlin.utils.getOrPutNullable
import org.jetbrains.org.objectweb.asm.*
import java.io.File
import java.util.*
import java.util.concurrent.ConcurrentMap
fun isInlineFunctionLineNumber(file: VirtualFile, lineNumber: Int, project: Project): Boolean {
if (ProjectRootsUtil.isProjectSourceFile(project, file)) {
@@ -119,7 +118,7 @@ class WeakBytecodeDebugInfoStorage : ConcurrentWeakFactoryMap<BinaryCacheKey, By
return BytecodeDebugInfo(smapData, lineNumberMapping)
}
override fun createMap(): ConcurrentMap<BinaryCacheKey, BytecodeDebugInfo?> {
override fun createMap(): Map<BinaryCacheKey, BytecodeDebugInfo?> {
return ContainerUtil.createConcurrentWeakKeyWeakValueMap()
}
}

View File

@@ -23,30 +23,20 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.util.text.StringUtilRt
import com.intellij.patterns.PatternCondition
import com.intellij.patterns.PatternConditionPlus
import com.intellij.patterns.PsiClassNamePatternCondition
import com.intellij.patterns.ValuePatternCondition
import com.intellij.psi.*
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiTreeUtil
import org.intellij.plugins.intelliLang.Configuration
import org.intellij.plugins.intelliLang.inject.InjectorUtils
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport
import org.intellij.plugins.intelliLang.inject.TemporaryPlacesRegistry
import org.intellij.plugins.intelliLang.inject.config.BaseInjection
import org.intellij.plugins.intelliLang.inject.config.InjectionPlace
import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport
import org.intellij.plugins.intelliLang.util.AnnotationUtilEx
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.patterns.KotlinFunctionPattern
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.runInReadActionWithWriteActionPriority
@@ -56,31 +46,30 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import java.util.*
import kotlin.collections.ArrayList
import org.jetbrains.kotlin.util.aliasImportMap
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class KotlinLanguageInjector(
private val configuration: Configuration,
private val project: Project,
private val temporaryPlacesRegistry: TemporaryPlacesRegistry
val configuration: Configuration,
val project: Project,
val temporaryPlacesRegistry: TemporaryPlacesRegistry
) : MultiHostInjector {
companion object {
private val STRING_LITERALS_REGEXP = "\"([^\"]*)\"".toRegex()
private val ABSENT_KOTLIN_INJECTION = BaseInjection("ABSENT_KOTLIN_BASE_INJECTION")
}
var annotationInjectionsEnabled = Registry.`is`("kotlin.annotation.injection.enabled", false)
private val kotlinSupport: KotlinLanguageInjectionSupport? by lazy {
val kotlinSupport: KotlinLanguageInjectionSupport? by lazy {
ArrayList(InjectorUtils.getActiveInjectionSupports()).filterIsInstance(KotlinLanguageInjectionSupport::class.java).firstOrNull()
}
private data class KotlinCachedInjection(val modificationCount: Long, val baseInjection: BaseInjection)
private var KtStringTemplateExpression.cachedInjectionWithModification: KotlinCachedInjection? by UserDataProperty(
Key.create<KotlinCachedInjection>("CACHED_INJECTION_WITH_MODIFICATION"))
Key.create<KotlinCachedInjection>("CACHED_INJECTION_WITH_MODIFICATION"))
override fun getLanguagesToInject(registrar: MultiHostRegistrar, context: PsiElement) {
val ktHost: KtStringTemplateExpression = context as? KtStringTemplateExpression ?: return
@@ -88,7 +77,7 @@ class KotlinLanguageInjector(
val support = kotlinSupport ?: return
if (!ProjectRootsUtil.isInProjectOrLibSource(ktHost.containingFile.originalFile)) return
if (!ProjectRootsUtil.isInProjectOrLibSource(ktHost)) return
val needImmediateAnswer = with(ApplicationManager.getApplication()) { isDispatchThread && !isUnitTestMode }
val kotlinCachedInjection = ktHost.cachedInjectionWithModification
@@ -144,9 +133,9 @@ class KotlinLanguageInjector(
@Suppress("FoldInitializerAndIfToElvis")
private fun computeBaseInjection(
ktHost: KtStringTemplateExpression,
support: KotlinLanguageInjectionSupport,
registrar: MultiHostRegistrar): BaseInjection? {
ktHost: KtStringTemplateExpression,
support: KotlinLanguageInjectionSupport,
registrar: MultiHostRegistrar): BaseInjection? {
val containingFile = ktHost.containingFile
val tempInjectedLanguage = temporaryPlacesRegistry.getLanguageFor(ktHost, containingFile)
@@ -168,10 +157,10 @@ class KotlinLanguageInjector(
private fun findInjectionInfo(place: KtElement, originalHost: Boolean = true): InjectionInfo? {
return injectWithExplicitCodeInstruction(place)
?: injectWithCall(place)
?: injectInAnnotationCall(place)
?: injectWithReceiver(place)
?: injectWithVariableUsage(place, originalHost)
?: injectWithCall(place)
?: injectWithReceiver(place)
?: injectWithVariableUsage(place, originalHost)
?: injectWithAnnotationEntry(place)
}
private fun injectWithExplicitCodeInstruction(host: KtElement): InjectionInfo? {
@@ -186,9 +175,9 @@ class KotlinLanguageInjector(
val callExpression = qualifiedExpression.selectorExpression as? KtCallExpression ?: return null
val callee = callExpression.calleeExpression ?: return null
if (isAnalyzeOff()) return null
if (isAnalyzeOff(qualifiedExpression.project)) return null
val kotlinInjections = configuration.getInjections(KOTLIN_SUPPORT_ID)
val kotlinInjections = Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID)
val calleeName = callee.text
val possibleNames = collectPossibleNames(kotlinInjections)
@@ -231,10 +220,11 @@ class KotlinLanguageInjector(
// Given place is not original host of the injection so we stop to prevent stepping through indirect references
if (!originalHost) return null
val ktHost: KtElement = host
val ktProperty = host.parent as? KtProperty ?: return null
if (ktProperty.initializer != host) return null
if (isAnalyzeOff()) return null
if (isAnalyzeOff(ktHost.project)) return null
val searchScope = LocalSearchScope(arrayOf(ktProperty.containingFile), "", true)
return ReferencesSearch.search(ktProperty, searchScope).asSequence().mapNotNull { psiReference ->
@@ -247,10 +237,10 @@ class KotlinLanguageInjector(
val ktHost: KtElement = host
val argument = ktHost.parent as? KtValueArgument ?: return null
val callExpression = PsiTreeUtil.getParentOfType(ktHost, KtCallElement::class.java) ?: return null
val callee = getNameReference(callExpression.calleeExpression) ?: return null
val callExpression = PsiTreeUtil.getParentOfType(ktHost, KtCallExpression::class.java) ?: return null
val callee = callExpression.calleeExpression ?: return null
if (isAnalyzeOff()) return null
if (isAnalyzeOff(ktHost.project)) return null
for (reference in callee.references) {
ProgressManager.checkCanceled()
@@ -273,44 +263,19 @@ class KotlinLanguageInjector(
return null
}
private fun getNameReference(callee: KtExpression?): KtNameReferenceExpression? {
if (callee is KtConstructorCalleeExpression)
return callee.constructorReferenceExpression as? KtNameReferenceExpression
return callee as? KtNameReferenceExpression
}
private fun injectInAnnotationCall(host: KtElement): InjectionInfo? {
if (!annotationInjectionsEnabled) return null
val argument = host.parent as? KtValueArgument ?: return null
val annotationEntry = argument.parent.parent as? KtCallElement ?: return null
if (!fastCheckInjectionsExists(annotationEntry)) return null
val calleeExpression = annotationEntry.calleeExpression ?: return null
val callee = getNameReference(calleeExpression)?.mainReference?.resolve()
when (callee) {
is PsiClass -> {
val psiClass = callee as? PsiClass ?: return null
val argumentName = argument.getArgumentName()?.asName?.identifier ?: "value"
val method = psiClass.findMethodsByName(argumentName, false).singleOrNull() ?: return null
return findInjection(method, configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID))
}
else -> return null
}
}
private fun injectionForJavaMethod(argument: KtValueArgument, javaMethod: PsiMethod): InjectionInfo? {
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
val psiParameter = javaMethod.parameterList.parameters.getOrNull(argumentIndex) ?: return null
val injectionInfo = findInjection(psiParameter, configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID))
val injectionInfo = findInjection(psiParameter, Configuration.getInstance().getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID))
if (injectionInfo != null) {
return injectionInfo
}
val annotations = AnnotationUtilEx.getAnnotationFrom(
psiParameter,
configuration.advancedConfiguration.languageAnnotationPair,
true)
psiParameter,
Configuration.getProjectInstance(psiParameter.project).advancedConfiguration.languageAnnotationPair,
true)
if (annotations.isNotEmpty()) {
return processAnnotationInjectionInner(annotations)
@@ -323,7 +288,7 @@ class KotlinLanguageInjector(
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
val ktParameter = ktFunction.valueParameters.getOrNull(argumentIndex) ?: return null
val patternInjection = findInjection(ktParameter, configuration.getInjections(KOTLIN_SUPPORT_ID))
val patternInjection = findInjection(ktParameter, Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID))
if (patternInjection != null) {
return patternInjection
}
@@ -341,6 +306,29 @@ class KotlinLanguageInjector(
return InjectionInfo(languageId, null, null)
}
private fun injectWithAnnotationEntry(host: KtElement): InjectionInfo? {
val argument = host.parent as? KtValueArgument ?: return null
val annotationEntry = PsiTreeUtil.getParentOfType(host, KtAnnotationEntry::class.java) ?: return null
if (isAnalyzeOff(host.project)) return null
val calleeReference = annotationEntry.calleeExpression?.constructorReferenceExpression?.mainReference
val callee = calleeReference?.resolve()
return when (callee) {
is KtFunction -> injectionForKotlinCall(argument, callee, calleeReference)
is PsiClass -> {
// Look for java injections for the PsiAnnotationMethod.
(argument.reference ?: argument.getArgumentName()?.referenceExpression?.mainReference)
?.let { it.resolve() as? PsiMethod }
?.let { findInjection(it, Configuration.getInstance().getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)) }
?.takeIf { injectionInfo ->
// Temporary forbid injection for SpEL because of inspections that gives warnings when host language is not Java.
injectionInfo.languageId != "SpEL"
}
}
else -> null
}
}
private fun findInjection(element: PsiElement?, injections: List<BaseInjection>): InjectionInfo? {
for (injection in injections) {
if (injection.acceptsPsiElement(element)) {
@@ -351,8 +339,8 @@ class KotlinLanguageInjector(
return null
}
private fun isAnalyzeOff(): Boolean {
return configuration.advancedConfiguration.dfaOption == Configuration.DfaOption.OFF
private fun isAnalyzeOff(project: Project): Boolean {
return Configuration.getProjectInstance(project).advancedConfiguration.dfaOption == Configuration.DfaOption.OFF
}
private fun processAnnotationInjectionInner(annotations: Array<PsiAnnotation>): InjectionInfo? {
@@ -362,52 +350,4 @@ class KotlinLanguageInjector(
return InjectionInfo(id, prefix, suffix)
}
private val injectableTargetClassShortNames = CachedValuesManager.getManager(project)
.createCachedValue({
CachedValueProvider.Result.create(HashSet<String>().apply {
for (injection in configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)) {
for (injectionPlace in injection.injectionPlaces) {
for (targetClassFQN in retrieveJavaPlaceTargetClassesFQNs(injectionPlace)) {
add(StringUtilRt.getShortName(targetClassFQN))
}
}
}
for (injection in configuration.getInjections(org.jetbrains.kotlin.idea.injection.KOTLIN_SUPPORT_ID)) {
for (injectionPlace in injection.injectionPlaces) {
for (targetClassFQN in retrieveKotlinPlaceTargetClassesFQNs(injectionPlace)) {
add(StringUtilRt.getShortName(targetClassFQN))
}
}
}
}, configuration)
}, false)
private fun fastCheckInjectionsExists(annotationEntry: KtCallElement): Boolean {
val referencedName = getNameReference(annotationEntry.calleeExpression)?.getReferencedName() ?: return false
val annotationShortName = annotationEntry.containingKtFile.aliasImportMap()[referencedName].singleOrNull() ?: referencedName
return annotationShortName in injectableTargetClassShortNames.value
}
private fun retrieveJavaPlaceTargetClassesFQNs(place: InjectionPlace): Collection<String> {
val classCondition = place.elementPattern.condition.conditions.firstOrNull { it.debugMethodName == "definedInClass" }
as? PatternConditionPlus<*, *> ?: return emptyList()
val psiClassNamePatternCondition = classCondition.valuePattern.condition.conditions.
firstIsInstanceOrNull<PsiClassNamePatternCondition>() ?: return emptyList()
val valuePatternCondition = psiClassNamePatternCondition.namePattern.condition.conditions.firstIsInstanceOrNull<ValuePatternCondition<String>>() ?: return emptyList()
return valuePatternCondition.values
}
private fun retrieveKotlinPlaceTargetClassesFQNs(place: InjectionPlace): Collection<String> {
val classNames = SmartList<String>()
fun collect(condition: PatternCondition<*>) {
when (condition) {
is PatternConditionPlus<*, *> -> condition.valuePattern.condition.conditions.forEach { collect(it) }
is KotlinFunctionPattern.DefinedInClassCondition -> classNames.add(condition.fqName)
}
}
place.elementPattern.condition.conditions.forEach { collect(it) }
return classNames
}
}
}

View File

@@ -123,7 +123,7 @@ object InlayScratchOutputHandler : ScratchOutputHandler {
return fontInfo.fontMetrics().stringWidth(text)
}
override fun paint(editor: Editor, g: Graphics, r: Rectangle, textAttributes: TextAttributes) {
override fun paint(editor: Editor, g: Graphics, r: Rectangle) {
val attributes = getAttributes()
val fgColor = attributes.foregroundColor ?: return
g.color = fgColor

View File

@@ -71,11 +71,10 @@ abstract class AbstractKotlinMavenInspectionTest : MavenImportingTestCase() {
val problemElements = runInspection(inspectionClass, myProject).problemElements
val actualProblems = problemElements
.keys()
.filter { it.name == "pom.xml" }
.map { problemElements.get(it) }
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
.filter { it.key.name == "pom.xml" }
.values
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
val actual = actualProblems
.map { SimplifiedProblemDescription(it.descriptionTemplate, it.psiElement.text.replace("\\s+".toRegex(), "")) to it }

View File

@@ -21,7 +21,6 @@ import com.intellij.execution.process.ProcessOutputTypes
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.annotations.NotNull
import org.jetbrains.kotlin.console.actions.logError
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.utils.repl.ReplEscapeType
@@ -50,7 +49,7 @@ class ReplOutputHandler(
override fun isSilentlyDestroyOnClose() = true
override fun notifyTextAvailable(text: String, key: Key<*>) {
override fun notifyTextAvailable(text: String, key: Key<*>?) {
// hide warning about adding test folder to classpath
if (text.startsWith("warning: classpath entry points to a non-existent location")) return

View File

@@ -1,6 +1,5 @@
<idea-plugin>
<id>org.jetbrains.kotlin</id>
<version>1.2</version>
<extensionPoints>
<extensionPoint qualifiedName="org.jetbrains.kotlin.diagnosticSuppressor"

View File

@@ -2,8 +2,6 @@
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPCommonFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPJSFrameworkSupportProvider"/>
@@ -61,6 +59,8 @@
<projectTaskRunner implementation="org.jetbrains.kotlin.idea.run.MultiplatformGradleProjectTaskRunner" order="first,before gradle"/>
<orderEnumerationHandlerFactory implementation="org.jetbrains.kotlin.idea.run.MultiplatformGradleOrderEnumeratorHandler$FactoryImpl" order="first"/>
<moduleBuilder builderClass="org.jetbrains.kotlin.gradle.kdsl.GradleModuleBuilder" />
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
@@ -77,6 +77,10 @@
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMultiplatformModuleBuilder"/>
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleJavaFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJavaFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJSFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleGroovyFrameworkSupportProvider" />
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
</extensions>
</idea-plugin>

View File

@@ -6,7 +6,7 @@
<version>@snapshot@</version>
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
<idea-version since-build="173.1" until-build="173.*"/>
<idea-version since-build="172.1" until-build="172.*"/>
<depends>com.intellij.modules.platform</depends>
<depends>com.intellij.modules.remoteServers</depends>
@@ -2786,6 +2786,8 @@
<resolveScopeProvider implementation="org.jetbrains.kotlin.idea.core.script.dependencies.KotlinScriptResolveScopeProvider"/>
<resolveScopeProvider implementation="org.jetbrains.kotlin.idea.core.script.dependencies.ScriptDependenciesResolveScopeProvider"/>
<codeInsight.intention.jvmCommonIntentionActionsFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.intentions.KotlinCommonIntentionActionsFactory"/>
<projectService serviceInterface="org.jetbrains.uast.kotlin.KotlinUastBindingContextProviderService"
serviceImplementation="org.jetbrains.uast.kotlin.internal.IdeaKotlinUastBindingContextProviderService"/>

View File

@@ -5,13 +5,13 @@
package org.jetbrains.kotlin.idea.formatter
import com.intellij.internal.statistic.AbstractProjectsUsagesCollector
import com.intellij.internal.statistic.beans.GroupDescriptor
import com.intellij.internal.statistic.beans.UsageDescriptor
import com.intellij.internal.statistic.utils.getEnumUsage
import com.intellij.openapi.project.Project
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
import org.jetbrains.kotlin.idea.util.compat.statistic.AbstractProjectsUsagesCollector
import org.jetbrains.kotlin.idea.util.compat.statistic.getEnumUsage
class KotlinFormatterUsageCollector : AbstractProjectsUsagesCollector() {
override fun getGroupId(): GroupDescriptor = GroupDescriptor.create(GROUP_ID)

View File

@@ -53,7 +53,7 @@ class KotlinRecursiveCallLineMarkerProvider : LineMarkerProvider {
val lineNumber = element.getLineNumber()
if (lineNumber !in markedLineNumbers && isRecursiveCall(element)) {
markedLineNumbers.add(lineNumber)
result.add(RecursiveMethodCallMarkerInfo(getElementForLineMark(element)))
result.add(RecursiveMethodCallMarkerInfo(element))
}
}
}
@@ -113,8 +113,8 @@ class KotlinRecursiveCallLineMarkerProvider : LineMarkerProvider {
return true
}
private class RecursiveMethodCallMarkerInfo(callElement: PsiElement)
: LineMarkerInfo<PsiElement>(
private class RecursiveMethodCallMarkerInfo(callElement: KtElement)
: LineMarkerInfo<KtElement>(
callElement,
callElement.textRange,
AllIcons.Gutter.RecursiveMethod,
@@ -125,7 +125,7 @@ class KotlinRecursiveCallLineMarkerProvider : LineMarkerProvider {
) {
override fun createGutterRenderer(): GutterIconRenderer? {
return object : LineMarkerInfo.LineMarkerGutterIconRenderer<PsiElement>(this) {
return object : LineMarkerInfo.LineMarkerGutterIconRenderer<KtElement>(this) {
override fun getClickAction() = null // to place breakpoint on mouse click
}
}
@@ -133,15 +133,6 @@ class KotlinRecursiveCallLineMarkerProvider : LineMarkerProvider {
}
internal fun getElementForLineMark(callElement: PsiElement): PsiElement =
when (callElement) {
is KtSimpleNameExpression -> callElement.getReferencedNameElement()
else ->
// a fallback,
//but who knows what to reference in KtArrayAccessExpression ?
generateSequence(callElement, { it.firstChild }).last()
}
private fun PsiElement.getLineNumber(): Int {
return PsiDocumentManager.getInstance(project).getDocument(containingFile)!!.getLineNumber(textOffset)
}

View File

@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider {
private class SuspendCallMarkerInfo(callElement: PsiElement, message: String) : LineMarkerInfo<PsiElement>(
private class SuspendCallMarkerInfo(callElement: KtElement, message: String) : LineMarkerInfo<KtElement>(
callElement,
callElement.textRange,
KotlinIcons.SUSPEND_CALL,
@@ -37,7 +37,7 @@ class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider {
GutterIconRenderer.Alignment.RIGHT
) {
override fun createGutterRenderer(): GutterIconRenderer? {
return object : LineMarkerInfo.LineMarkerGutterIconRenderer<PsiElement>(this) {
return object : LineMarkerInfo.LineMarkerGutterIconRenderer<KtElement>(this) {
override fun getClickAction(): AnAction? = null
}
}
@@ -61,9 +61,9 @@ class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider {
markedLineNumbers += lineNumber
result += if (element is KtForExpression) {
SuspendCallMarkerInfo(getElementForLineMark(element.loopRange!!), "Suspending iteration")
SuspendCallMarkerInfo(element.loopRange!!, "Suspending iteration")
} else {
SuspendCallMarkerInfo(getElementForLineMark(element), "Suspend function call")
SuspendCallMarkerInfo(element, "Suspend function call")
}
}
}

View File

@@ -12,7 +12,6 @@ import com.intellij.codeInsight.daemon.impl.MarkerType
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator
import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask
import com.intellij.icons.AllIcons
import com.intellij.ide.util.PsiClassOrFunctionalExpressionListCellRenderer
import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.openapi.editor.colors.CodeInsightColors
import com.intellij.openapi.editor.colors.EditorColorsManager
@@ -151,20 +150,12 @@ interface TestableLineMarkerNavigator {
fun getTargetsPopupDescriptor(element: PsiElement?): NavigationPopupDescriptor?
}
private class SubclassRenderer: PsiClassOrFunctionalExpressionListCellRenderer() {
override fun getComparingObject(element: NavigatablePsiElement?): Comparable<Nothing> {
val baseText = super.getComparingObject(element)
val moduleName = element?.module?.name ?: return baseText
return "$baseText [$moduleName]"
}
}
private val SUBCLASSED_CLASS = MarkerType(
"SUBCLASSED_CLASS",
{ getPsiClass(it)?.let { MarkerType.getSubclassedClassTooltip(it) } },
object : LineMarkerNavigator() {
override fun browse(e: MouseEvent?, element: PsiElement?) {
getPsiClass(element)?.let { MarkerType.navigateToSubclassedClass(e, it, SubclassRenderer()) }
getPsiClass(element)?.let { MarkerType.navigateToSubclassedClass(e, it) }
}
})

View File

@@ -0,0 +1,261 @@
/*
* 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.idea.intentions
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
import com.intellij.codeInsight.intention.MethodInsertionInfo
import com.intellij.codeInsight.intention.QuickFixFactory
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.insertMembersAfter
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder
import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder.Target.CONSTRUCTOR
import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder.Target.FUNCTION
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.uast.UClass
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
class KotlinCommonIntentionActionsFactory : JvmCommonIntentionActionsFactory() {
override fun createChangeModifierAction(declaration: UDeclaration, modifier: String, shouldPresent: Boolean): IntentionAction? {
val kModifierOwner = declaration.asKtElement<KtModifierListOwner>()
?: throw IllegalArgumentException("$declaration is expected to contain KtLightElement with KtModifierListOwner")
val (kToken, shouldPresentMapped) = if (PsiModifier.FINAL == modifier)
KtTokens.OPEN_KEYWORD to !shouldPresent
else
javaPsiModifiersMapping[modifier] to shouldPresent
if (kToken == null) return null
return if (shouldPresentMapped)
AddModifierFix.createIfApplicable(kModifierOwner, kToken)
else
RemoveModifierFix(kModifierOwner, kToken, false)
}
override fun createAddBeanPropertyActions(uClass: UClass,
propertyName: String,
visibilityModifier: String,
propertyType: PsiType,
setterRequired: Boolean,
getterRequired: Boolean): List<IntentionAction> {
fun addPropertyFix(lateinit: Boolean = false) =
Fix(uClass,
"Add property",
"Add '${if (lateinit) "lateinit " else ""}" +
"${if (setterRequired) "var" else "val"}' property '$propertyName' to '${uClass.name}'")
{ uClass ->
val visibilityStr = javaVisibilityMapping.getValue(visibilityModifier)
val psiFactory = KtPsiFactory(uClass)
val modifiersString = if (lateinit) "lateinit $visibilityStr" else visibilityStr
val function = psiFactory.createProperty(
modifiersString,
propertyName,
typeString(propertyType),
setterRequired,
if (lateinit) null else "TODO(\"initialize me\")")
val ktClassOrObject = uClass.asKtElement<KtClassOrObject>()!!
insertMembersAfter(null, ktClassOrObject, listOf(function), null)
}
if (setterRequired)
return listOf(addPropertyFix(), addPropertyFix(lateinit = true))
else
return listOf(addPropertyFix())
}
override fun createAddCallableMemberActions(info: MethodInsertionInfo): List<IntentionAction> =
when (info) {
is MethodInsertionInfo.Method ->
createAddMethodAction(info)?.let { listOf(it) } ?: emptyList()
is MethodInsertionInfo.Constructor ->
createAddConstructorActions(info)
}
companion object {
val javaPsiModifiersMapping = mapOf(
PsiModifier.PRIVATE to KtTokens.PRIVATE_KEYWORD,
PsiModifier.PUBLIC to KtTokens.PUBLIC_KEYWORD,
PsiModifier.PROTECTED to KtTokens.PUBLIC_KEYWORD,
PsiModifier.ABSTRACT to KtTokens.ABSTRACT_KEYWORD
)
val javaVisibilityMapping: Map<String, String> = mapOf(
PsiModifier.PRIVATE to Visibilities.PRIVATE.displayName,
PsiModifier.PUBLIC to "",
PsiModifier.PROTECTED to Visibilities.PROTECTED.displayName,
PsiModifier.PACKAGE_LOCAL to Visibilities.INTERNAL.displayName
).withDefault { Visibilities.DEFAULT_VISIBILITY.displayName }
fun typeString(str: PsiType): String {
var typeName: String? = when (str) {
PsiType.VOID -> ""
PsiType.INT -> "kotlin.Int"
PsiType.LONG -> "kotlin.Long"
PsiType.SHORT -> "kotlin.Short"
PsiType.BOOLEAN -> "kotlin.Boolean"
PsiType.BYTE -> "kotlin.Byte"
PsiType.CHAR -> "kotlin.Char"
PsiType.DOUBLE -> "kotlin.Double"
PsiType.FLOAT -> "kotlin.Float"
else -> null
}
if (typeName == null)
typeName = JavaToKotlinClassMap.mapJavaToKotlin(FqName(str.canonicalText), DefaultBuiltIns.Instance)?.fqNameSafe?.asString()
return typeName ?: str.canonicalText
}
}
private inline fun <reified T : KtElement> UElement.asKtElement(): T? =
(psi as? KtLightElement<*, *>?)?.kotlinOrigin as? T
private fun CallableBuilder.paramsFromInfo(info: MethodInsertionInfo) {
for ((index, param) in info.parameters.withIndex()) {
param(param.name ?: "arg${index + 1}", typeString(param.type))
}
}
private fun createAddMethodAction(info: MethodInsertionInfo.Method): IntentionAction? {
val visibilityStr = info.modifiers.map { javaVisibilityMapping.get(it) ?: it }.joinToString(" ")
val functionString = CallableBuilder(FUNCTION).apply {
modifier(visibilityStr)
typeParams()
name(info.name)
paramsFromInfo(info)
info.returnType.let {
when (it) {
PsiType.VOID -> noReturnType()
else -> returnType(typeString(it))
}
}
blockBody("")
}
return Fix(info.containingClass, "Add method", "Add method '${info.name}' to '${info.containingClass.name}'") {
uClass ->
val psiFactory = KtPsiFactory(uClass)
val function = psiFactory.createFunction(functionString.asString())
val ktClassOrObject = uClass.asKtElement<KtClassOrObject>()!!
insertMembersAfter(null, ktClassOrObject, listOf(function), ktClassOrObject.declarations.lastOrNull())
}
}
private fun createAddConstructorActions(info: MethodInsertionInfo.Constructor): List<IntentionAction> {
val constructorString = CallableBuilder(CONSTRUCTOR).apply {
modifier("")
typeParams()
name()
paramsFromInfo(info)
noReturnType()
blockBody("")
}.asString()
val primaryConstructor = info.containingClass.asKtElement<KtClass>()!!.primaryConstructor
val addConstructorAction = if (primaryConstructor == null)
Fix(info.containingClass,
"Add method",
"Add primary constructor to '${info.containingClass.name}'",
{ uClass ->
val psiFactory = KtPsiFactory(uClass)
val constructor = psiFactory.createSecondaryConstructor(constructorString)
val ktClass = uClass.asKtElement<KtClass>()!!
val newPrimaryConstructor = ktClass.createPrimaryConstructorIfAbsent()
newPrimaryConstructor.valueParameterList!!.replace(constructor.valueParameterList!!)
ShortenReferences.DEFAULT.process(newPrimaryConstructor)
})
else Fix(info.containingClass,
"Add method",
"Add secondary constructor to '${info.containingClass.name}'",
{ uClass ->
val psiFactory = KtPsiFactory(uClass)
val constructor = psiFactory.createSecondaryConstructor(constructorString)
val ktClassOrObject = uClass.asKtElement<KtClassOrObject>()!!
insertMembersAfter(null, ktClassOrObject, listOf(constructor), null)
})
val changePrimaryConstructorAction = run {
if (primaryConstructor == null) return@run null
QuickFixFactory.getInstance()
.createChangeMethodSignatureFromUsageFix(
LightClassUtil.getLightClassMethod(primaryConstructor)!!,
fakeParametersExpressions(info.parameters),
PsiSubstitutor.EMPTY, info.containingClass, false, 2
).takeIf { it.isAvailable(info.containingClass.project, null, info.containingClass.containingFile) }
}
return listOf(changePrimaryConstructorAction, addConstructorAction).filterNotNull()
}
private fun fakeParametersExpressions(parameters: List<PsiParameter>): Array<PsiExpression> =
when {
parameters.isEmpty() -> emptyArray<PsiExpression>()
else -> JavaPsiFacade.getElementFactory(parameters.first().project)
.createParameterList(
parameters.map { it.name }.toTypedArray(),
parameters.map { it.type }.toTypedArray()
).parameters.map { FakeExpressionFromParameter(it) }.toTypedArray()
}
private class FakeExpressionFromParameter(private val psiParam: PsiParameter) : PsiReferenceExpressionImpl() {
override fun getText(): String = psiParam.name!!
override fun getProject(): Project = psiParam.project
override fun getParent(): PsiElement = psiParam.parent
override fun getType(): PsiType? = psiParam.type
override fun isValid(): Boolean = true
override fun getContainingFile(): PsiFile = psiParam.containingFile
override fun getReferenceName(): String? = psiParam.name
override fun resolve(): PsiElement? = psiParam
}
private class Fix(uClass: UClass, private val familyName: String, private val text: String, private val action: (uClass: UClass) -> Unit) : LocalQuickFixAndIntentionActionOnPsiElement(uClass) {
override fun getFamilyName(): String = familyName
override fun getText(): String = text
override fun invoke(project: Project, file: PsiFile, editor: Editor?, startElement: PsiElement, endElement: PsiElement) =
action(startElement as UClass)
}
}

View File

@@ -9,8 +9,8 @@ import com.intellij.codeInsight.hints.InlayParameterHintsExtension
import com.intellij.internal.statistic.UsagesCollector
import com.intellij.internal.statistic.beans.GroupDescriptor
import com.intellij.internal.statistic.beans.UsageDescriptor
import com.intellij.internal.statistic.utils.getBooleanUsage
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.util.compat.statistic.getBooleanUsage
class KotlinInlayParameterHintsUsageCollector : UsagesCollector() {
override fun getGroupId(): GroupDescriptor = GroupDescriptor.create(GROUP_ID)

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.FileModificationService
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
abstract class KotlinCrossLanguageQuickFixAction<out T : PsiElement>(element: T) : QuickFixActionBase<T>(element) {
override val isCrossLanguageFix: Boolean
get() = true
override final fun invoke(project: Project, editor: Editor?, file: PsiFile) {
val element = element
if (element != null && FileModificationService.getInstance().prepareFileForWrite(element.containingFile)) {
invokeImpl(project, editor, file)
}
}
protected abstract fun invokeImpl(project: Project, editor: Editor?, file: PsiFile)
}

View File

@@ -17,18 +17,42 @@
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.FileModificationService
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.psi.CREATEBYPATTERN_MAY_NOT_REFORMAT
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
abstract class KotlinQuickFixAction<out T : PsiElement>(element: T) : QuickFixActionBase<T>(element) {
protected open fun isAvailable(project: Project, editor: Editor?, file: KtFile) = true
abstract class KotlinQuickFixAction<out T : PsiElement>(element: T) : IntentionAction {
private val elementPointer = element.createSmartPointer()
override fun isAvailableImpl(project: Project, editor: Editor?, file: PsiFile): Boolean {
val ktFile = file as? KtFile ?: return false
return isAvailable(project, editor, ktFile)
protected val element: T?
get() = elementPointer.element
final override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
if (ApplicationManager.getApplication().isUnitTestMode) {
CREATEBYPATTERN_MAY_NOT_REFORMAT = true
}
try {
val element = element ?: return false
return element.isValid &&
!element.project.isDisposed &&
(file.manager.isInProject(file) || file is KtCodeFragment) &&
(file is KtFile) &&
isAvailable(project, editor, file)
}
finally {
CREATEBYPATTERN_MAY_NOT_REFORMAT = false
}
}
protected open fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean {
return true
}
final override fun invoke(project: Project, editor: Editor?, file: PsiFile) {

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.psi.CREATEBYPATTERN_MAY_NOT_REFORMAT
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
abstract class QuickFixActionBase<out T : PsiElement>(element: T) : IntentionAction {
private val elementPointer = element.createSmartPointer()
protected val element: T?
get() = elementPointer.element
open val isCrossLanguageFix: Boolean = false
protected open fun isAvailableImpl(project: Project, editor: Editor?, file: PsiFile) = true
final override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
if (ApplicationManager.getApplication().isUnitTestMode) {
CREATEBYPATTERN_MAY_NOT_REFORMAT = true
}
try {
val element = element ?: return false
return element.isValid &&
!element.project.isDisposed &&
(file.manager.isInProject(file) || file is KtCodeFragment) &&
(file is KtFile || isCrossLanguageFix) &&
isAvailableImpl(project, editor, file)
}
finally {
CREATEBYPATTERN_MAY_NOT_REFORMAT = false
}
}
override fun startInWriteAction() = true
}

View File

@@ -464,34 +464,16 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val psiFactory = KtPsiFactory(currentFile)
val modifiers = buildString {
val modifierList = callableInfo.modifierList?.copied() ?: psiFactory.createEmptyModifierList()
val visibilityKeyword = modifierList.visibilityModifierType()
if (visibilityKeyword == null) {
val defaultVisibility =
if (callableInfo.isAbstract) ""
else if (containingElement is KtClassOrObject
&& !(containingElement is KtClass && containingElement.isInterface())
&& containingElement.isAncestor(config.originalElement)
&& callableInfo.kind != CallableKind.CONSTRUCTOR) "private "
else if (isExtension) "private "
else ""
append(defaultVisibility)
}
// TODO: Get rid of isAbstract
if (callableInfo.isAbstract
&& containingElement is KtClass
&& !containingElement.isInterface()
&& !modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
modifierList.appendModifier(KtTokens.ABSTRACT_KEYWORD)
}
val text = modifierList.normalize().text
if (text.isNotEmpty()) {
append("$text ")
}
}
val modifiers =
if (callableInfo.isAbstract) {
if (containingElement is KtClass && containingElement.isInterface()) "" else "abstract "
}
else if (containingElement is KtClassOrObject
&& !(containingElement is KtClass && containingElement.isInterface())
&& containingElement.isAncestor(config.originalElement)
&& callableInfo.kind != CallableKind.CONSTRUCTOR) "private "
else if (isExtension) "private "
else ""
val isExpectClassMember by lazy {
containingElement is KtClassOrObject && containingElement.resolveToDescriptorIfAny()?.isExpect ?: false
@@ -500,7 +482,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val declaration: KtNamedDeclaration = when (callableInfo.kind) {
CallableKind.FUNCTION, CallableKind.CONSTRUCTOR -> {
val body = when {
callableInfo is ConstructorInfo -> if (callableInfo.withBody) "{\n\n}" else ""
callableInfo.kind == CallableKind.CONSTRUCTOR -> ""
callableInfo.isAbstract -> ""
containingElement is KtClass && containingElement.hasModifier(KtTokens.EXTERNAL_KEYWORD) -> ""
containingElement is KtObjectDeclaration && containingElement.hasModifier(KtTokens.EXTERNAL_KEYWORD) -> ""
@@ -508,12 +490,14 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
&& containingElement.parent.parent is KtClass
&& (containingElement.parent.parent as KtClass).hasModifier(KtTokens.EXTERNAL_KEYWORD) -> ""
isExpectClassMember -> ""
else -> "{\n\n}"
else -> "{}"
}
@Suppress("USELESS_CAST") // KT-10755
if (callableInfo is FunctionInfo) {
psiFactory.createFunction("${modifiers}fun<> $header $body") as KtNamedDeclaration
val operatorModifier = if (callableInfo.isOperator) "operator " else ""
val infixModifier = if (callableInfo.isInfix) "infix " else ""
psiFactory.createFunction("$modifiers$infixModifier${operatorModifier}fun<> $header $body") as KtNamedDeclaration
}
else if ((callableInfo as ConstructorInfo).isPrimary) {
val constructorText = if (modifiers.isNotEmpty()) "${modifiers}constructor$paramList" else paramList
@@ -572,11 +556,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
return assignmentToReplace.replace(declaration) as KtCallableDeclaration
}
val container = if (containingElement is KtClass && callableInfo.isForCompanion) {
containingElement.getOrCreateCompanionObject()
}
else containingElement
val declarationInPlace = placeDeclarationInContainer(declaration, container, config.originalElement, jetFileToEdit)
val declarationInPlace = placeDeclarationInContainer(declaration, containingElement, config.originalElement, jetFileToEdit)
if (declarationInPlace is KtSecondaryConstructor) {
val containingClass = declarationInPlace.containingClassOrObject!!
@@ -613,11 +593,14 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
private fun setupTypeReferencesForShortening(declaration: KtNamedDeclaration,
parameterTypeExpressions: List<TypeExpression>) {
parameterTypeExpressions: List<TypeExpression>): List<KtElement> {
val typeRefsToShorten = ArrayList<KtElement>()
if (config.isExtension) {
val receiverTypeText = receiverTypeCandidate!!.theType.renderLong(typeParameterNameMap).first()
val replacingTypeRef = KtPsiFactory(declaration).createType(receiverTypeText)
(declaration as KtCallableDeclaration).setReceiverTypeReference(replacingTypeRef)!!
val newTypeRef = (declaration as KtCallableDeclaration).setReceiverTypeReference(replacingTypeRef)!!
typeRefsToShorten.add(newTypeRef)
}
val returnTypeRefs = declaration.getReturnTypeReferences()
@@ -628,6 +611,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
if (returnType != null) {
// user selected a given type
replaceWithLongerName(returnTypeRefs, returnType)
typeRefsToShorten.addAll(declaration.getReturnTypeReferences())
}
}
@@ -646,6 +630,11 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
}
}
val expandedValueParameters = declaration.getValueParameters()
parameterIndicesToShorten.mapNotNullTo(typeRefsToShorten) { expandedValueParameters[it].typeReference }
return typeRefsToShorten
}
private fun postprocessDeclaration(declaration: KtNamedDeclaration) {
@@ -656,22 +645,18 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
if (TypeUtils.isNullableType(returnType) || KotlinBuiltIns.isPrimitiveType(returnType)) return
declaration.addModifier(KtTokens.LATEINIT_KEYWORD)
}
if (callableInfo.isAbstract) {
val containingClass = declaration.containingClassOrObject
if (containingClass is KtClass && containingClass.isInterface()) {
declaration.removeModifier(KtTokens.ABSTRACT_KEYWORD)
}
}
}
private fun setupDeclarationBody(func: KtDeclarationWithBody) {
if (func !is KtNamedFunction && func !is KtPropertyAccessor) return
if (skipReturnType && callableInfo is FunctionInfo && callableInfo.preferEmptyBody) return
val oldBody = func.bodyExpression ?: return
val templateKind = when (func) {
is KtSecondaryConstructor -> TemplateKind.SECONDARY_CONSTRUCTOR
is KtNamedFunction, is KtPropertyAccessor -> TemplateKind.FUNCTION
else -> throw AssertionError("Unexpected declaration: " + func.getElementTextWithContext())
}
val bodyText = getFunctionBodyTextFromTemplate(
func.project,
TemplateKind.FUNCTION,
templateKind,
if (callableInfo.name.isNotEmpty()) callableInfo.name else null,
if (skipReturnType) "Unit" else (func as? KtFunction)?.typeReference?.text ?: "",
receiverClassDescriptor?.importableFqName ?: receiverClassDescriptor?.name?.let { FqName.topLevel(it) }
@@ -778,7 +763,13 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
// add parameter name to the template
val possibleNamesFromExpression = parameter.typeInfo.getPossibleNamesFromExpression(currentFileContext)
val possibleNames = arrayOf(*parameter.nameSuggestions.toTypedArray(), *possibleNamesFromExpression)
val preferredName = parameter.preferredName
val possibleNames = if (preferredName != null) {
arrayOf(preferredName, *possibleNamesFromExpression)
}
else {
possibleNamesFromExpression
}
// figure out suggested names for each type option
val parameterTypeToNamesMap = HashMap<String, Array<String>>()
@@ -972,14 +963,6 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
if (newDeclaration is KtProperty) {
newDeclaration.getter?.let { setupDeclarationBody(it) }
if (newDeclaration.getter == null
&& newDeclaration.initializer == null
&& callableInfo is PropertyInfo
&& callableInfo.withInitializer
&& !callableInfo.isLateinitPreferred) {
newDeclaration.initializer = KtPsiFactory(newDeclaration).createExpression("TODO(\"initialize me\")")
}
}
val callElement = config.originalElement as? KtCallElement
@@ -990,9 +973,9 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
CodeStyleManager.getInstance(project).reformat(newDeclaration)
// change short type names to fully qualified ones (to be shortened below)
setupTypeReferencesForShortening(newDeclaration, parameterTypeExpressions)
val typeRefsToShorten = setupTypeReferencesForShortening(newDeclaration, parameterTypeExpressions)
if (!transformToJavaMemberIfApplicable(newDeclaration)) {
elementsToShorten.add(newDeclaration)
elementsToShorten.addAll(typeRefsToShorten)
setupEditor(newDeclaration)
}
}
@@ -1119,24 +1102,17 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
}
container is KtClassOrObject -> {
var sibling: PsiElement? = container.declarations.lastOrNull { it::class == declaration::class }
if (sibling == null && declaration is KtProperty) {
sibling = container.getBody()?.lBrace
}
insertMember(null, container, declaration, sibling)
insertMember(null, container, declaration, container.declarations.lastOrNull())
}
else -> throw AssertionError("Invalid containing element: ${container.text}")
}
if (declaration !is KtPrimaryConstructor) {
val parent = declarationInPlace.parent
calcNecessaryEmptyLines(declarationInPlace, false).let {
if (it > 0) parent.addBefore(psiFactory.createNewLine(it), declarationInPlace)
}
calcNecessaryEmptyLines(declarationInPlace, true).let {
if (it > 0) parent.addAfter(psiFactory.createNewLine(it), declarationInPlace)
}
val parent = declarationInPlace.parent
calcNecessaryEmptyLines(declarationInPlace, false).let {
if (it > 0) parent.addBefore(psiFactory.createNewLine(it), declarationInPlace)
}
calcNecessaryEmptyLines(declarationInPlace, true).let {
if (it > 0) parent.addAfter(psiFactory.createNewLine(it), declarationInPlace)
}
return declarationInPlace
}

View File

@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.ClassInfo
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.getResolvableApproximations
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
@@ -71,10 +70,6 @@ abstract class TypeInfo(val variance: Variance) {
(builder.placement as CallablePlacement.WithReceiver).receiverTypeCandidate.theType.getPossibleSupertypes(variance, builder)
}
class ByExplicitCandidateTypes(val types: List<KotlinType>) : TypeInfo(Variance.INVARIANT) {
override fun getPossibleTypes(builder: CallableBuilder) = types
}
abstract class DelegatingTypeInfo(val delegate: TypeInfo): TypeInfo(delegate.variance) {
override val substitutionsAllowed: Boolean = delegate.substitutionsAllowed
override fun getPossibleNamesFromExpression(bindingContext: BindingContext) = delegate.getPossibleNamesFromExpression(bindingContext)
@@ -160,10 +155,8 @@ fun TypeInfo.ofThis() = TypeInfo.OfThis(this)
*/
class ParameterInfo(
val typeInfo: TypeInfo,
val nameSuggestions: List<String>
) {
constructor(typeInfo: TypeInfo, preferredName: String? = null): this(typeInfo, listOfNotNull(preferredName))
}
val preferredName: String? = null
)
enum class CallableKind {
FUNCTION,
@@ -178,17 +171,14 @@ abstract class CallableInfo (
val returnTypeInfo: TypeInfo,
val possibleContainers: List<KtElement>,
val typeParameterInfos: List<TypeInfo>,
val isForCompanion: Boolean = false,
val modifierList: KtModifierList? = null
val isAbstract: Boolean = false
) {
abstract val kind: CallableKind
abstract val parameterInfos: List<ParameterInfo>
val isAbstract get() = modifierList?.hasModifier(KtTokens.ABSTRACT_KEYWORD) == true
abstract fun copy(receiverTypeInfo: TypeInfo = this.receiverTypeInfo,
possibleContainers: List<KtElement> = this.possibleContainers,
modifierList: KtModifierList? = this.modifierList): CallableInfo
isAbstract: Boolean = this.isAbstract): CallableInfo
}
class FunctionInfo(name: String,
@@ -197,59 +187,42 @@ class FunctionInfo(name: String,
possibleContainers: List<KtElement> = Collections.emptyList(),
override val parameterInfos: List<ParameterInfo> = Collections.emptyList(),
typeParameterInfos: List<TypeInfo> = Collections.emptyList(),
isForCompanion: Boolean = false,
modifierList: KtModifierList? = null,
val preferEmptyBody: Boolean = false
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isForCompanion, modifierList) {
val isOperator: Boolean = false,
val isInfix: Boolean = false,
isAbstract: Boolean = false
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isAbstract) {
override val kind: CallableKind get() = CallableKind.FUNCTION
override fun copy(
receiverTypeInfo: TypeInfo,
possibleContainers: List<KtElement>,
modifierList: KtModifierList?
) = FunctionInfo(
override fun copy(receiverTypeInfo: TypeInfo, possibleContainers: List<KtElement>, isAbstract: Boolean) = FunctionInfo(
name,
receiverTypeInfo,
returnTypeInfo,
possibleContainers,
parameterInfos,
typeParameterInfos,
isForCompanion,
modifierList
isOperator,
isInfix,
isAbstract
)
}
class ClassWithPrimaryConstructorInfo(
val classInfo: ClassInfo,
expectedTypeInfo: TypeInfo,
modifierList: KtModifierList? = null
): CallableInfo(
classInfo.name, TypeInfo.Empty, expectedTypeInfo.forceNotNull(), Collections.emptyList(), classInfo.typeArguments, false, modifierList = modifierList
class ClassWithPrimaryConstructorInfo(val classInfo: ClassInfo, expectedTypeInfo: TypeInfo): CallableInfo(
classInfo.name, TypeInfo.Empty, expectedTypeInfo.forceNotNull(), Collections.emptyList(), classInfo.typeArguments, false
) {
override val kind: CallableKind get() = CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR
override val parameterInfos: List<ParameterInfo> get() = classInfo.parameterInfos
override fun copy(
receiverTypeInfo: TypeInfo,
possibleContainers: List<KtElement>,
modifierList: KtModifierList?
) = throw UnsupportedOperationException()
override fun copy(receiverTypeInfo: TypeInfo, possibleContainers: List<KtElement>, isAbstract: Boolean) = throw UnsupportedOperationException()
}
class ConstructorInfo(
override val parameterInfos: List<ParameterInfo>,
val targetClass: PsiElement,
val isPrimary: Boolean = false,
modifierList: KtModifierList? = null,
val withBody: Boolean = false
): CallableInfo("", TypeInfo.Empty, TypeInfo.Empty, Collections.emptyList(), Collections.emptyList(), false, modifierList = modifierList) {
val isPrimary: Boolean = false
): CallableInfo("", TypeInfo.Empty, TypeInfo.Empty, Collections.emptyList(), Collections.emptyList(), false) {
override val kind: CallableKind get() = CallableKind.CONSTRUCTOR
override fun copy(
receiverTypeInfo: TypeInfo,
possibleContainers: List<KtElement>,
modifierList: KtModifierList?
) = throw UnsupportedOperationException()
override fun copy(receiverTypeInfo: TypeInfo, possibleContainers: List<KtElement>, isAbstract: Boolean) = throw UnsupportedOperationException()
}
class PropertyInfo(name: String,
@@ -258,35 +231,20 @@ class PropertyInfo(name: String,
val writable: Boolean,
possibleContainers: List<KtElement> = Collections.emptyList(),
typeParameterInfos: List<TypeInfo> = Collections.emptyList(),
val isLateinitPreferred: Boolean = false,
isForCompanion: Boolean = false,
modifierList: KtModifierList? = null,
val withInitializer: Boolean = false
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isForCompanion, modifierList) {
isAbstract: Boolean = false,
val isLateinitPreferred: Boolean = false
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isAbstract) {
override val kind: CallableKind get() = CallableKind.PROPERTY
override val parameterInfos: List<ParameterInfo> get() = Collections.emptyList()
override fun copy(
receiverTypeInfo: TypeInfo,
possibleContainers: List<KtElement>,
modifierList: KtModifierList?
) = copyProperty(receiverTypeInfo, possibleContainers, modifierList)
fun copyProperty(
receiverTypeInfo: TypeInfo = this.receiverTypeInfo,
possibleContainers: List<KtElement> = this.possibleContainers,
modifierList: KtModifierList? = this.modifierList,
isLateinitPreferred: Boolean = this.isLateinitPreferred
) = PropertyInfo(
override fun copy(receiverTypeInfo: TypeInfo, possibleContainers: List<KtElement>, isAbstract: Boolean) = PropertyInfo(
name,
receiverTypeInfo,
returnTypeInfo,
writable,
possibleContainers,
typeParameterInfos,
isLateinitPreferred,
isForCompanion,
modifierList,
withInitializer
isAbstract,
isLateinitPreferred
)
}

View File

@@ -29,13 +29,11 @@ fun setupEditorSelection(editor: Editor, declaration: KtNamedDeclaration) {
val caretModel = editor.caretModel
val selectionModel = editor.selectionModel
val offset = when (declaration) {
is KtPrimaryConstructor -> declaration.getConstructorKeyword()?.endOffset ?: declaration.valueParameterList?.startOffset
is KtSecondaryConstructor -> declaration.getConstructorKeyword().endOffset
else -> declaration.nameIdentifier?.endOffset
if (declaration is KtSecondaryConstructor) {
caretModel.moveToOffset(declaration.getConstructorKeyword().endOffset)
}
if (offset != null) {
caretModel.moveToOffset(offset)
else {
caretModel.moveToOffset(declaration.nameIdentifier!!.endOffset)
}
fun positionBetween(left: PsiElement, right: PsiElement) {

View File

@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import java.util.*
@@ -56,12 +55,8 @@ object CreateBinaryOperationActionFactory : CreateCallableMemberFromUsageFactory
}
val parameters = Collections.singletonList(ParameterInfo(TypeInfo(argumentExpr, Variance.IN_VARIANCE)))
val isOperator = token != KtTokens.IDENTIFIER
return FunctionInfo(
operationName,
receiverType,
returnType,
parameterInfos = parameters,
modifierList = KtPsiFactory(element).createModifierList(if (isOperator) KtTokens.OPERATOR_KEYWORD else KtTokens.INFIX_KEYWORD)
)
return FunctionInfo(operationName, receiverType, returnType, parameterInfos = parameters,
isOperator = isOperator,
isInfix = !isOperator)
}
}

View File

@@ -153,10 +153,7 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
if (!receiverType.isAbstract() && TypeUtils.getAllSupertypes(receiverType).all { !it.isAbstract() }) return null
return mainCallable.copy(
receiverTypeInfo = receiverTypeInfo,
possibleContainers = emptyList(),
modifierList = KtPsiFactory(originalExpression).createModifierList(KtTokens.ABSTRACT_KEYWORD))
return mainCallable.copy(receiverTypeInfo = receiverTypeInfo, possibleContainers = emptyList(), isAbstract = true)
}
protected fun getCallableWithReceiverInsideExtension(

View File

@@ -17,18 +17,14 @@
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.ide.util.EditorHelper
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.quickfix.KotlinCrossLanguageQuickFixAction
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
import org.jetbrains.kotlin.idea.refactoring.canRefactor
import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary
@@ -37,31 +33,30 @@ import org.jetbrains.kotlin.idea.util.application.executeCommand
import org.jetbrains.kotlin.idea.util.isAbstract
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import java.util.*
open class CreateCallableFromUsageFix<E : KtElement>(
originalExpression: E,
callableInfos: List<CallableInfo>
class CreateCallableFromUsageFix<E : KtElement>(
originalExpression: E,
callableInfos: List<CallableInfo>
) : CreateCallableFromUsageFixBase<E>(originalExpression, callableInfos, false)
class CreateExtensionCallableFromUsageFix<E : KtElement>(
originalExpression: E,
callableInfos: List<CallableInfo>
originalExpression: E,
callableInfos: List<CallableInfo>
) : CreateCallableFromUsageFixBase<E>(originalExpression, callableInfos, true), LowPriorityAction
abstract class CreateCallableFromUsageFixBase<E : KtElement>(
originalExpression: E,
protected val callableInfos: List<CallableInfo>,
val isExtension: Boolean
) : KotlinCrossLanguageQuickFixAction<E>(originalExpression) {
originalExpression: E,
private val callableInfos: List<CallableInfo>,
val isExtension: Boolean
) : CreateFromUsageFixBase<E>(originalExpression) {
init {
assert(callableInfos.isNotEmpty()) { "No CallableInfos: ${originalExpression.getElementTextWithContext()}" }
assert (callableInfos.isNotEmpty()) { "No CallableInfos: ${originalExpression.getElementTextWithContext()}" }
if (callableInfos.size > 1) {
val receiverSet = callableInfos.mapTo(HashSet()) { it.receiverTypeInfo }
val receiverSet = callableInfos.mapTo(HashSet<TypeInfo>()) { it.receiverTypeInfo }
if (receiverSet.size > 1) throw AssertionError("All functions must have common receiver: $receiverSet")
val possibleContainerSet = callableInfos.mapTo(HashSet()) { it.possibleContainers }
val possibleContainerSet = callableInfos.mapTo(HashSet<List<KtElement>>()) { it.possibleContainers }
if (possibleContainerSet.size > 1) throw AssertionError("All functions must have common containers: $possibleContainerSet")
}
}
@@ -82,8 +77,6 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
return if (isExtension || declaration.canRefactor()) declaration else null
}
override fun getFamilyName(): String = KotlinBundle.message("create.from.usage.family")
override fun getText(): String {
val element = element ?: return ""
val receiverTypeInfo = callableInfos.first().receiverTypeInfo
@@ -106,18 +99,20 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
val receiverType = if (!receiverTypeInfo.isOfThis) {
CallableBuilderConfiguration(callableInfos, element, isExtension = isExtension)
.createBuilder()
.computeTypeCandidates(receiverTypeInfo)
.firstOrNull()
?.theType
} else null
.createBuilder()
.computeTypeCandidates(receiverTypeInfo)
.firstOrNull()
?.theType
}
else null
if (receiverType != null) {
if (isExtension) {
val receiverTypeText = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(receiverType)
val isFunctionType = receiverType.constructor.declarationDescriptor is FunctionClassDescriptor
append(if (isFunctionType) "($receiverTypeText)" else receiverTypeText).append('.')
} else {
}
else {
receiverType.constructor.declarationDescriptor?.let {
append(IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderClassifierName(it)).append('.')
}
@@ -132,10 +127,12 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
return StringBuilder().apply {
append("Create ")
val receiverInfo = receiverTypeInfo
if (!callableInfos.any { it.isAbstract }) {
if (isExtension) {
append("extension ")
} else if (receiverTypeInfo != TypeInfo.Empty) {
}
else if (receiverInfo !is TypeInfo.Empty) {
append("member ")
}
}
@@ -144,12 +141,12 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
}.toString()
}
override fun isAvailableImpl(project: Project, editor: Editor?, file: PsiFile): Boolean {
override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean {
val element = element ?: return false
val receiverInfo = callableInfos.first().receiverTypeInfo
if (receiverInfo == TypeInfo.Empty) {
if (receiverInfo is TypeInfo.Empty) {
if (callableInfos.any { it is PropertyInfo && it.possibleContainers.isEmpty() }) return false
return !isExtension
}
@@ -176,25 +173,12 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
}
}
override fun invokeImpl(project: Project, editor: Editor?, file: PsiFile) {
if (editor == null) return
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val callableInfo = callableInfos.first()
val fileForBuilder: KtFile
val editorForBuilder: Editor
if (file is KtFile) {
fileForBuilder = file
editorForBuilder = editor
} else {
fileForBuilder = element.containingKtFile
EditorHelper.openInEditor(element)
editorForBuilder = FileEditorManager.getInstance(project).selectedTextEditor!!
}
val callableBuilder =
CallableBuilderConfiguration(callableInfos, element as KtElement, fileForBuilder, editorForBuilder, isExtension).createBuilder()
CallableBuilderConfiguration(callableInfos, element as KtElement, file, editor!!, isExtension).createBuilder()
fun runBuilder(placement: CallablePlacement) {
callableBuilder.placement = placement
@@ -207,24 +191,19 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
}
val popupTitle = "Choose target class or interface"
val receiverTypeInfo = callableInfo.receiverTypeInfo
val receiverTypeCandidates = callableBuilder.computeTypeCandidates(receiverTypeInfo).let {
if (callableInfo.isAbstract)
it.filter { it.theType.isAbstract() }
else if (!isExtension && receiverTypeInfo != TypeInfo.Empty)
it.filter { !it.theType.isTypeParameter() }
else
it
val receiverTypeCandidates = callableBuilder.computeTypeCandidates(callableInfo.receiverTypeInfo).let {
if (callableInfo.isAbstract) it.filter { it.theType.isAbstract() } else it
}
if (receiverTypeCandidates.isNotEmpty()) {
val containers = receiverTypeCandidates
.mapNotNull { candidate -> getDeclarationIfApplicable(project, candidate)?.let { candidate to it } }
.mapNotNull { candidate -> getDeclarationIfApplicable(project, candidate)?.let { candidate to it } }
chooseContainerElementIfNecessary(containers, editor, popupTitle, false, { it.second }) {
runBuilder(CallablePlacement.WithReceiver(it.first))
}
} else {
assert(receiverTypeInfo == TypeInfo.Empty) {
}
else {
assert(callableInfo.receiverTypeInfo is TypeInfo.Empty) {
"No receiver type candidates: ${element.text} in ${file.text}"
}

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.psi.SmartPsiElementPointer
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.quickfix.IntentionActionPriority
@@ -36,7 +35,7 @@ abstract class CreateCallableMemberFromUsageFactory<E : KtElement>(
originalElementPointer: SmartPsiElementPointer<E>,
priority: IntentionActionPriority,
quickFixDataFactory: () -> List<CallableInfo>?,
quickFixFactory: (E, List<CallableInfo>) -> IntentionAction?
quickFixFactory: (E, List<CallableInfo>) -> CreateFromUsageFixBase<E>?
): QuickFixWithDelegateFactory {
return QuickFixWithDelegateFactory(priority) {
val data = quickFixDataFactory().orEmpty()

View File

@@ -23,10 +23,8 @@ import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallableInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
import org.jetbrains.kotlin.types.Variance
@@ -54,11 +52,6 @@ object CreateComponentFunctionActionFactory : CreateCallableMemberFromUsageFacto
val entry = entries[componentNumber]
val returnTypeInfo = TypeInfo(entry, Variance.OUT_VARIANCE)
return FunctionInfo(
name.identifier,
ownerTypeInfo,
returnTypeInfo,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
)
return FunctionInfo(name.identifier, ownerTypeInfo, returnTypeInfo, isOperator = true)
}
}

View File

@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.Callab
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
@@ -36,12 +34,7 @@ object CreateGetFunctionActionFactory : CreateGetSetFunctionActionFactory(isGet
val parameters = element.indexExpressions.map { ParameterInfo(TypeInfo(it, Variance.IN_VARIANCE)) }
val returnType = TypeInfo(element, Variance.OUT_VARIANCE)
return FunctionInfo(
OperatorNameConventions.GET.asString(),
arrayType,
returnType,
Collections.emptyList(),
parameters,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
OperatorNameConventions.GET.asString(), arrayType, returnType, Collections.emptyList(), parameters, isOperator = true
)
}
}

View File

@@ -24,9 +24,7 @@ import org.jetbrains.kotlin.idea.project.builtIns
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallableInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -40,11 +38,6 @@ object CreateHasNextFunctionActionFactory : CreateCallableMemberFromUsageFactory
DiagnosticFactory.cast(diagnostic, Errors.HAS_NEXT_MISSING, Errors.HAS_NEXT_FUNCTION_NONE_APPLICABLE)
val ownerType = TypeInfo(diagnosticWithParameters.a, Variance.IN_VARIANCE)
val returnType = TypeInfo(element.builtIns.booleanType, Variance.OUT_VARIANCE)
return FunctionInfo(
OperatorNameConventions.HAS_NEXT.asString(),
ownerType,
returnType,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
)
return FunctionInfo(OperatorNameConventions.HAS_NEXT.asString(), ownerType, returnType, isOperator = true)
}
}

View File

@@ -23,9 +23,7 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.Callab
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -50,12 +48,6 @@ object CreateInvokeFunctionActionFactory : CreateCallableMemberFromUsageFactory<
}
val returnType = TypeInfo(element, Variance.OUT_VARIANCE)
return FunctionInfo(
OperatorNameConventions.INVOKE.asString(),
receiverType,
returnType,
parameterInfos = parameters,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
)
return FunctionInfo(OperatorNameConventions.INVOKE.asString(), receiverType, returnType, parameterInfos = parameters, isOperator = true)
}
}

View File

@@ -23,11 +23,9 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.Callab
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.guessTypes
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.Variance
@@ -59,11 +57,6 @@ object CreateIteratorFunctionActionFactory : CreateCallableMemberFromUsageFactor
returnJetType.isMarkedNullable,
returnJetType.memberScope)
val returnType = TypeInfo(newReturnJetType, Variance.OUT_VARIANCE)
return FunctionInfo(
OperatorNameConventions.ITERATOR.asString(),
iterableType,
returnType,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
)
return FunctionInfo(OperatorNameConventions.ITERATOR.asString(), iterableType, returnType, isOperator = true)
}
}

View File

@@ -23,10 +23,8 @@ import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallableInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -41,11 +39,6 @@ object CreateNextFunctionActionFactory : CreateCallableMemberFromUsageFactory<Kt
val variableExpr = element.loopParameter ?: element.destructuringDeclaration ?: return null
val returnType = TypeInfo(variableExpr as KtExpression, Variance.OUT_VARIANCE)
return FunctionInfo(
OperatorNameConventions.NEXT.asString(),
ownerType,
returnType,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
)
return FunctionInfo(OperatorNameConventions.NEXT.asString(), ownerType, returnType, isOperator = true)
}
}

View File

@@ -29,10 +29,8 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.Callab
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
@@ -71,15 +69,13 @@ object CreatePropertyDelegateAccessorsActionFactory : CreateCallableMemberFromUs
val callableInfos = SmartList<CallableInfo>()
val psiFactory = KtPsiFactory(element)
if (isApplicableForAccessor(propertyDescriptor.getter)) {
val getterInfo = FunctionInfo(
name = OperatorNameConventions.GET_VALUE.asString(),
receiverTypeInfo = accessorReceiverType,
returnTypeInfo = TypeInfo(propertyType, Variance.OUT_VARIANCE),
parameterInfos = listOf(thisRefParam, metadataParam),
modifierList = psiFactory.createModifierList(KtTokens.OPERATOR_KEYWORD)
isOperator = true
)
callableInfos.add(getterInfo)
}
@@ -91,7 +87,7 @@ object CreatePropertyDelegateAccessorsActionFactory : CreateCallableMemberFromUs
receiverTypeInfo = accessorReceiverType,
returnTypeInfo = TypeInfo(builtIns.unitType, Variance.OUT_VARIANCE),
parameterInfos = listOf(thisRefParam, metadataParam, newValueParam),
modifierList = psiFactory.createModifierList(KtTokens.OPERATOR_KEYWORD)
isOperator = true
)
callableInfos.add(setterInfo)
}

View File

@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.Callab
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.Variance
@@ -59,12 +58,7 @@ object CreateSetFunctionActionFactory : CreateGetSetFunctionActionFactory(isGet
val returnType = TypeInfo(builtIns.unitType, Variance.OUT_VARIANCE)
return FunctionInfo(
OperatorNameConventions.SET.asString(),
arrayType,
returnType,
Collections.emptyList(),
parameters,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
OperatorNameConventions.SET.asString(), arrayType, returnType, Collections.emptyList(), parameters, isOperator = true
)
}
}

View File

@@ -21,8 +21,6 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.Callab
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -41,11 +39,6 @@ object CreateUnaryOperationActionFactory: CreateCallableMemberFromUsageFactory<K
val receiverType = TypeInfo(receiverExpr, Variance.IN_VARIANCE)
val returnType = if (incDec) TypeInfo.ByReceiverType(Variance.OUT_VARIANCE) else TypeInfo(element, Variance.OUT_VARIANCE)
return FunctionInfo(
operationName.asString(),
receiverType,
returnType,
modifierList = KtPsiFactory(element).createModifierList(KtTokens.OPERATOR_KEYWORD)
)
return FunctionInfo(operationName.asString(), receiverType, returnType, isOperator = true)
}
}

View File

@@ -1,389 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.quickfix.crossLanguage
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.QuickFixFactory
import com.intellij.lang.jvm.*
import com.intellij.lang.jvm.actions.*
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.appendModifier
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreateCallableFromUsageFix
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver
import org.jetbrains.kotlin.load.java.lazy.child
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaTypeParameterDescriptor
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeAttributes
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeImpl
import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeParameterImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.annotations.JVM_FIELD_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.supertypes
class KotlinElementActionsFactory : JvmElementActionsFactory() {
companion object {
val javaPsiModifiersMapping = mapOf(
JvmModifier.PRIVATE to KtTokens.PRIVATE_KEYWORD,
JvmModifier.PUBLIC to KtTokens.PUBLIC_KEYWORD,
JvmModifier.PROTECTED to KtTokens.PUBLIC_KEYWORD,
JvmModifier.ABSTRACT to KtTokens.ABSTRACT_KEYWORD
)
}
private class FakeExpressionFromParameter(private val psiParam: PsiParameter) : PsiReferenceExpressionImpl() {
override fun getText(): String = psiParam.name!!
override fun getProject(): Project = psiParam.project
override fun getParent(): PsiElement = psiParam.parent
override fun getType(): PsiType? = psiParam.type
override fun isValid(): Boolean = true
override fun getContainingFile(): PsiFile = psiParam.containingFile
override fun getReferenceName(): String? = psiParam.name
override fun resolve(): PsiElement? = psiParam
}
private class ModifierBuilder(
private val targetContainer: KtElement,
private val allowJvmStatic: Boolean = true
) {
private val psiFactory = KtPsiFactory(targetContainer.project)
val modifierList = psiFactory.createEmptyModifierList()
private fun JvmModifier.transformAndAppend(): Boolean {
javaPsiModifiersMapping[this]?.let {
modifierList.appendModifier(it)
return true
}
when (this) {
JvmModifier.STATIC -> {
if (allowJvmStatic && targetContainer is KtClassOrObject) {
addAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME)
}
}
JvmModifier.ABSTRACT -> modifierList.appendModifier(KtTokens.ABSTRACT_KEYWORD)
JvmModifier.FINAL -> modifierList.appendModifier(KtTokens.FINAL_KEYWORD)
else -> return false
}
return true
}
var isValid = true
private set
fun addJvmModifier(modifier: JvmModifier) {
isValid = isValid && modifier.transformAndAppend()
}
fun addJvmModifiers(modifiers: Iterable<JvmModifier>) {
modifiers.forEach { addJvmModifier(it) }
}
fun addAnnotation(fqName: FqName) {
if (!isValid) return
modifierList.add(psiFactory.createAnnotationEntry("@${fqName.asString()}"))
}
}
class CreatePropertyFix(
private val targetClass: JvmClass,
contextElement: KtElement,
propertyInfo: PropertyInfo
) : CreateCallableFromUsageFix<KtElement>(contextElement, listOf(propertyInfo)) {
override fun getFamilyName() = "Add property"
override fun getText(): String {
val info = callableInfos.first() as PropertyInfo
return buildString {
append("Add '")
if (info.isLateinitPreferred) {
append("lateinit ")
}
append(if (info.writable) "var" else "val")
append("' property '${info.name}' to '${targetClass.name}'")
}
}
}
private fun JvmClass.toKtClassOrFile(): KtElement? {
val psi = sourceElement
return when (psi) {
is KtClassOrObject -> psi
is KtLightClassForSourceDeclaration -> psi.kotlinOrigin
is KtLightClassForFacade -> psi.files.firstOrNull()
else -> null
}
}
private inline fun <reified T : KtElement> JvmElement.toKtElement() = sourceElement?.unwrapped as? T
private fun fakeParametersExpressions(parameters: List<JvmParameter>, project: Project): Array<PsiExpression>? =
when {
parameters.isEmpty() -> emptyArray()
else -> JavaPsiFacade
.getElementFactory(project)
.createParameterList(
parameters.map { it.name }.toTypedArray(),
parameters.map { it.type as? PsiType ?: return null }.toTypedArray()
)
.parameters
.map(::FakeExpressionFromParameter)
.toTypedArray()
}
private fun PsiType.collectTypeParameters(): List<PsiTypeParameter> {
val results = ArrayList<PsiTypeParameter>()
accept(
object : PsiTypeVisitor<Unit>() {
override fun visitArrayType(arrayType: PsiArrayType) {
arrayType.componentType.accept(this)
}
override fun visitClassType(classType: PsiClassType) {
(classType.resolve() as? PsiTypeParameter)?.let { results += it }
classType.parameters.forEach { it.accept(this) }
}
override fun visitWildcardType(wildcardType: PsiWildcardType) {
wildcardType.bound?.accept(this)
}
}
)
return results
}
private fun PsiType.resolveToKotlinType(resolutionFacade: ResolutionFacade): KotlinType? {
val typeParameters = collectTypeParameters()
val components = resolutionFacade.getFrontendService(JavaResolverComponents::class.java)
val rootContext = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY) { null }
val dummyPackageDescriptor = MutablePackageFragmentDescriptor(resolutionFacade.moduleDescriptor, FqName("dummy"))
val dummyClassDescriptor = ClassDescriptorImpl(
dummyPackageDescriptor,
Name.identifier("Dummy"),
Modality.FINAL,
ClassKind.CLASS,
emptyList(),
SourceElement.NO_SOURCE,
false
)
val typeParameterResolver = object : TypeParameterResolver {
override fun resolveTypeParameter(javaTypeParameter: JavaTypeParameter): TypeParameterDescriptor? {
val psiTypeParameter = (javaTypeParameter as JavaTypeParameterImpl).psi
val index = typeParameters.indexOf(psiTypeParameter)
if (index < 0) return null
return LazyJavaTypeParameterDescriptor(rootContext.child(this), javaTypeParameter, index, dummyClassDescriptor)
}
}
val typeResolver = JavaTypeResolver(rootContext, typeParameterResolver)
val attributes = JavaTypeAttributes(TypeUsage.COMMON)
return typeResolver.transformJavaType(JavaTypeImpl.create(this), attributes).approximateFlexibleTypes(preferNotNull = true)
}
private fun ExpectedTypes.toKotlinTypeInfo(resolutionFacade: ResolutionFacade): TypeInfo {
val candidateTypes = flatMapTo(LinkedHashSet<KotlinType>()) {
val ktType = (it.theType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: return@flatMapTo emptyList()
when (it.theKind) {
ExpectedType.Kind.EXACT, ExpectedType.Kind.SUBTYPE -> listOf(ktType)
ExpectedType.Kind.SUPERTYPE -> listOf(ktType) + ktType.supertypes()
}
}
if (candidateTypes.isEmpty()) {
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
return TypeInfo(nullableAnyType, Variance.INVARIANT)
}
return TypeInfo.ByExplicitCandidateTypes(candidateTypes.toList())
}
override fun createChangeModifierActions(target: JvmModifiersOwner, request: MemberRequest.Modifier): List<IntentionAction> {
val kModifierOwner = target.toKtElement<KtModifierListOwner>() ?: return emptyList()
val modifier = request.modifier
val shouldPresent = request.shouldPresent
val (kToken, shouldPresentMapped) = if (JvmModifier.FINAL == modifier)
KtTokens.OPEN_KEYWORD to !shouldPresent
else
javaPsiModifiersMapping[modifier] to shouldPresent
if (kToken == null) return emptyList()
val action = if (shouldPresentMapped)
AddModifierFix.createIfApplicable(kModifierOwner, kToken)
else
RemoveModifierFix(kModifierOwner, kToken, false)
return listOfNotNull(action)
}
override fun createAddConstructorActions(targetClass: JvmClass, request: MemberRequest.Constructor): List<IntentionAction> {
val targetKtClass = targetClass.toKtClassOrFile() as? KtClass ?: return emptyList()
if (request.typeParameters.isNotEmpty()) return emptyList()
val modifierBuilder = ModifierBuilder(targetKtClass).apply { addJvmModifiers(request.modifiers) }
if (!modifierBuilder.isValid) return emptyList()
val resolutionFacade = targetKtClass.getResolutionFacade()
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
val parameterInfos = request.parameters.mapIndexed { index, param ->
val ktType = (param.type as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
val name = param.name ?: "arg${index + 1}"
ParameterInfo(TypeInfo(ktType, Variance.IN_VARIANCE), listOf(name))
}
val needPrimary = !targetKtClass.hasExplicitPrimaryConstructor()
val constructorInfo = ConstructorInfo(
parameterInfos,
targetKtClass,
isPrimary = needPrimary,
modifierList = modifierBuilder.modifierList,
withBody = true
)
val addConstructorAction = object : CreateCallableFromUsageFix<KtElement>(targetKtClass, listOf(constructorInfo)) {
override fun getFamilyName() = "Add method"
override fun getText() = "Add ${if (needPrimary) "primary" else "secondary"} constructor to '${targetClass.name}'"
}
val changePrimaryConstructorAction = run {
val primaryConstructor = targetKtClass.primaryConstructor ?: return@run null
val lightMethod = primaryConstructor.toLightMethods().firstOrNull() ?: return@run null
val project = targetKtClass.project
val fakeParametersExpressions = fakeParametersExpressions(request.parameters, project) ?: return@run null
QuickFixFactory.getInstance()
.createChangeMethodSignatureFromUsageFix(
lightMethod,
fakeParametersExpressions,
PsiSubstitutor.EMPTY,
targetKtClass,
false,
2
).takeIf { it.isAvailable(project, null, targetKtClass.containingFile) }
}
return listOfNotNull(changePrimaryConstructorAction, addConstructorAction)
}
override fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List<IntentionAction> {
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifier(request.visibilityModifier) }
if (!modifierBuilder.isValid) return emptyList()
val resolutionFacade = targetContainer.getResolutionFacade()
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
val ktType = (request.propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
val propertyInfo = PropertyInfo(
request.propertyName,
TypeInfo.Empty,
TypeInfo(ktType, Variance.INVARIANT),
request.setterRequired,
listOf(targetContainer),
modifierList = modifierBuilder.modifierList,
withInitializer = true
)
val propertyInfos = if (request.setterRequired) {
listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true))
}
else {
listOf(propertyInfo)
}
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
}
override fun createAddFieldActions(targetClass: JvmClass, request: CreateFieldRequest): List<IntentionAction> {
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
val modifierBuilder = ModifierBuilder(targetContainer, allowJvmStatic = false).apply {
addJvmModifiers(request.modifiers)
addAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME)
}
if (!modifierBuilder.isValid) return emptyList()
val resolutionFacade = targetContainer.getResolutionFacade()
val typeInfo = request.fieldType.toKotlinTypeInfo(resolutionFacade)
val writable = JvmModifier.FINAL !in request.modifiers
val propertyInfo = PropertyInfo(
request.fieldName,
TypeInfo.Empty,
typeInfo,
writable,
listOf(targetContainer),
isForCompanion = JvmModifier.STATIC in request.modifiers,
modifierList = modifierBuilder.modifierList,
withInitializer = true
)
val propertyInfos = if (writable) {
listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true))
}
else {
listOf(propertyInfo)
}
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
}
override fun createAddMethodActions(targetClass: JvmClass, request: CreateMethodRequest): List<IntentionAction> {
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifiers(request.modifiers) }
if (!modifierBuilder.isValid) return emptyList()
val resolutionFacade = targetContainer.getResolutionFacade()
val returnTypeInfo = request.returnType.toKotlinTypeInfo(resolutionFacade)
val parameterInfos = request.parameters.map { (suggestedNames, expectedTypes) ->
ParameterInfo(expectedTypes.toKotlinTypeInfo(resolutionFacade), suggestedNames.names.toList())
}
val functionInfo = FunctionInfo(
request.methodName,
TypeInfo.Empty,
returnTypeInfo,
listOf(targetContainer),
parameterInfos,
isForCompanion = JvmModifier.STATIC in request.modifiers,
modifierList = modifierBuilder.modifierList,
preferEmptyBody = true
)
val action = object : CreateCallableFromUsageFix<KtElement>(targetContainer, listOf(functionInfo)) {
override fun getFamilyName() = "Add method"
override fun getText() = "Add method '${request.methodName}' to '${targetClass.name}'"
}
return listOf(action)
}
}

View File

@@ -163,8 +163,7 @@ class MoveKotlinDeclarationsHandler : MoveHandlerDelegate() {
}
private fun canMove(elements: Array<out PsiElement>, targetContainer: PsiElement?, editorMode: Boolean): Boolean {
if (targetContainer != null && !isValidTarget(targetContainer, elements)) return false
if (!super.canMove(elements, targetContainer)) return false
val container = getUniqueContainer(elements) ?: return false
if (container is KtClassOrObject && targetContainer != null && targetContainer !is KtClassOrObject && elements.size > 1) {

View File

@@ -35,8 +35,6 @@ import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDe
import com.intellij.usageView.UsageInfo
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.*
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightFieldImpl
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.idea.KotlinBundle
@@ -137,15 +135,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
fun findUsagesByJavaProcessor(element: PsiElement, forceReferencedElementUnwrapping: Boolean): NonCodeUsageSearchInfo? {
val javaUsages = ArrayList<UsageInfo>()
val elementToPassToJava = when (element) {
is KtLightFieldImpl<*> -> object : KtLightField by element {
// Suppress walking through initializer compiled PSI (it doesn't contain any reference expressions anyway)
override fun getInitializer() = null
}
else -> element
}
val searchInfo = super.findUsages(elementToPassToJava, asLightElements(allElementsToDelete), javaUsages)
val searchInfo = super.findUsages(element, asLightElements(allElementsToDelete), javaUsages)
javaUsages.filterIsInstance<SafeDeleteOverridingMethodUsageInfo>().mapNotNullTo(deleteSet) { it.element }

View File

@@ -16,65 +16,18 @@
package org.jetbrains.kotlin.idea.slicer
import com.intellij.codeInspection.dataFlow.Nullness
import com.intellij.ide.util.treeView.AbstractTreeStructure
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.psi.PsiElement
import com.intellij.slicer.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.guessTypes
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isPlainWithEscapes
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.isNullabilityFlexible
class KotlinSliceProvider : SliceLanguageSupportProvider, SliceUsageTransformer {
companion object {
val LEAF_ELEMENT_EQUALITY = object : SliceLeafEquality() {
override fun substituteElement(element: PsiElement) = (element as? KtReference)?.resolve() ?: element
}
}
class KotlinGroupByNullnessAction(treeBuilder: SliceTreeBuilder) : GroupByNullnessActionBase(treeBuilder) {
override fun isAvailable() = true
}
val leafAnalyzer by lazy { SliceLeafAnalyzer(LEAF_ELEMENT_EQUALITY, this) }
val nullnessAnalyzer: SliceNullnessAnalyzerBase by lazy {
object : SliceNullnessAnalyzerBase(LEAF_ELEMENT_EQUALITY, this) {
override fun checkNullness(element: PsiElement?): Nullness {
val types = when (element) {
is KtCallableDeclaration -> listOfNotNull((element.resolveToDescriptorIfAny() as? CallableDescriptor)?.returnType)
is KtDeclaration -> emptyList()
is KtExpression -> listOfNotNull(element.analyze(BodyResolveMode.PARTIAL).getType(element))
else -> emptyList()
}
return when {
types.isEmpty() -> return Nullness.UNKNOWN
types.all { KotlinBuiltIns.isNullableNothing(it) } -> Nullness.NULLABLE
types.any { it.isError || TypeUtils.isNullableType(it) || it.isNullabilityFlexible() } -> Nullness.UNKNOWN
else -> Nullness.NOT_NULL
}
}
}
}
class KotlinSliceProvider : SliceLanguageSupportProvider {
override fun createRootUsage(element: PsiElement, params: SliceAnalysisParams) = KotlinSliceUsage(element, params)
override fun transform(usage: SliceUsage): Collection<SliceUsage>? {
if (usage is KotlinSliceUsage) return null
return listOf(KotlinSliceUsage(usage.element, usage.parent, 0, false))
}
override fun getExpressionAtCaret(atCaret: PsiElement?, dataFlowToThis: Boolean): KtExpression? {
val element =
atCaret?.parentsWithSelf
@@ -102,17 +55,14 @@ class KotlinSliceProvider : SliceLanguageSupportProvider, SliceUsageTransformer
override fun getRenderer() = KotlinSliceUsageCellRenderer
override fun startAnalyzeLeafValues(structure: AbstractTreeStructure, finalRunnable: Runnable) {
leafAnalyzer.startAnalyzeValues(structure, finalRunnable)
}
override fun startAnalyzeNullness(structure: AbstractTreeStructure, finalRunnable: Runnable) {
nullnessAnalyzer.startAnalyzeNullness(structure, finalRunnable)
}
override fun registerExtraPanelActions(group: DefaultActionGroup, builder: SliceTreeBuilder) {
if (builder.dataFlowToThis) {
group.add(GroupByLeavesAction(builder))
group.add(KotlinGroupByNullnessAction(builder))
}
}
}

View File

@@ -19,13 +19,10 @@ package org.jetbrains.kotlin.idea.slicer
import com.intellij.psi.PsiElement
import com.intellij.slicer.SliceAnalysisParams
import com.intellij.slicer.SliceUsage
import com.intellij.usageView.UsageInfo
import com.intellij.util.Processor
import org.jetbrains.kotlin.psi.KtExpression
open class KotlinSliceUsage : SliceUsage {
class UsageInfoLambdaWrapper(element: PsiElement) : UsageInfo(element)
val lambdaLevel: Int
val forcedExpressionMode: Boolean
@@ -45,18 +42,6 @@ open class KotlinSliceUsage : SliceUsage {
return KotlinSliceUsage(element, parent, lambdaLevel, forcedExpressionMode)
}
override fun getUsageInfo(): UsageInfo {
val originalInfo = super.getUsageInfo()
if (lambdaLevel > 0 && forcedExpressionMode) {
val element = originalInfo.element ?: return originalInfo
// Do not let IDEA consider usages of the same anonymous function as duplicates when their levels differ
return UsageInfoLambdaWrapper(element)
}
return originalInfo
}
override fun canBeLeaf() = element != null && lambdaLevel == 0
public override fun processUsagesFlownDownTo(element: PsiElement, uniqueProcessor: Processor<SliceUsage>) {
InflowSlicer(element as? KtExpression ?: return, uniqueProcessor, this).processChildren()
}

View File

@@ -0,0 +1,12 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.util.compat.statistic
typealias AbstractProjectsUsagesCollector = com.intellij.internal.statistic.AbstractApplicationUsagesCollector
fun getEnumUsage(key: String, value: Enum<*>?) = com.intellij.internal.statistic.getEnumUsage(key, value)
fun getBooleanUsage(key: String, value: Boolean) = com.intellij.internal.statistic.getBooleanUsage(key, value)

View File

@@ -177,7 +177,7 @@ private fun <T : BinaryVersion> getLibraryRootsWithAbiIncompatibleVersion(
"Only library roots were requested, and only class files should be indexed with the $id key. " +
"File: ${indexedFile.path}"
)
badRoots.add(BinaryVersionedFile(VfsUtil.getLocalFile(libraryRoot), version, supportedVersion))
badRoots.add(BinaryVersionedFile(com.intellij.util.PathUtil.getLocalFile(libraryRoot), version, supportedVersion))
}
}

View File

@@ -1,6 +1,6 @@
operator fun Any.get(a: Int) {
if (a > 0) {
<lineMarker descr="Recursive call">this</lineMarker>[a - 1]
<lineMarker descr="Recursive call">this[a - 1]</lineMarker>
}
}

View File

@@ -1,6 +0,0 @@
class K {
fun foo(i: Int, s: String): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}

View File

@@ -1,6 +0,0 @@
// "Add method 'foo' to 'K'" "true"
class J {
void test(K k) {
boolean b = k.<caret>foo(1, "2");
}
}

View File

@@ -1,6 +0,0 @@
// "Add method 'foo' to 'K'" "true"
class J {
void test(K k) {
boolean b = k.<caret>foo(1, "2");
}
}

View File

@@ -1,9 +0,0 @@
class K {
companion object {
@JvmStatic
fun foo(i: Int, s: String): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}

View File

@@ -1,7 +0,0 @@
// "Add method 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test() {
boolean b = K.<caret>foo(1, "2");
}
}

View File

@@ -1,7 +0,0 @@
// "Add method 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test() {
boolean b = K.<caret>foo(1, "2");
}
}

View File

@@ -1,7 +0,0 @@
@file:JvmName("TestKt")
fun test() {}
fun foo(i: Int, s: String): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

View File

@@ -1,6 +0,0 @@
// "Add method 'foo' to 'TestKt'" "true"
class J {
void test() {
boolean b = TestKt.<caret>foo(1, "2");
}
}

View File

@@ -1,3 +0,0 @@
@file:JvmName("TestKt")
fun test() {}

View File

@@ -1,6 +0,0 @@
// "Add method 'foo' to 'TestKt'" "true"
class J {
void test() {
boolean b = TestKt.<caret>foo(1, "2");
}
}

View File

@@ -1,7 +1,5 @@
// "Create type parameter 'Test' in class 'C'" "false"
// ACTION: Add 'testng' to classpath
// ACTION: Add 'JUnit4' to classpath
// ACTION: Add 'JUnit5.0' to classpath
// ACTION: Create annotation 'Test'
// ACTION: Make internal
// ACTION: Make private

View File

@@ -1,5 +0,0 @@
class K {
@JvmField
lateinit var foo: String
}

View File

@@ -1,7 +0,0 @@
// "Add 'lateinit var' property 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test(K k) {
String s = k.<caret>foo;
}
}

View File

@@ -1,7 +0,0 @@
// "Add 'lateinit var' property 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test(K k) {
String s = k.<caret>foo;
}
}

View File

@@ -1,5 +0,0 @@
class K {
@JvmField
var foo: String = TODO("initialize me")
}

View File

@@ -1,7 +0,0 @@
// "Add 'var' property 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test(K k) {
String s = k.<caret>foo;
}
}

View File

@@ -1,7 +0,0 @@
// "Add 'var' property 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test(K k) {
String s = k.<caret>foo;
}
}

View File

@@ -1,7 +0,0 @@
class K {
companion object {
@JvmField
var foo: String = TODO("initialize me")
}
}

View File

@@ -1,7 +0,0 @@
// "Add 'var' property 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test() {
String s = K.<caret>foo;
}
}

View File

@@ -1,7 +0,0 @@
// "Add 'var' property 'foo' to 'K'" "true"
// WITH_RUNTIME
class J {
void test() {
String s = K.<caret>foo;
}
}

View File

@@ -1,6 +0,0 @@
@file:JvmName("TestKt")
fun test() {}
@JvmField
var foo: String = TODO("initialize me")

View File

@@ -1,7 +0,0 @@
// "Add 'var' property 'foo' to 'TestKt'" "true"
// WITH_RUNTIME
class J {
void test() {
String s = TestKt.<caret>foo;
}
}

View File

@@ -1,3 +0,0 @@
@file:JvmName("TestKt")
fun test() {}

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