Compare commits

...

41 Commits

Author SHA1 Message Date
Dmitry Gridin
28570a681f AddOperatorModifierInspection: decrease severity to INFORMATION
#KT-32796 Fixed

(cherry picked from commit a9f0d1a53b)
2019-07-22 11:40:09 +03:00
Dmitry Gridin
23c77c4432 GradleBuildScript: throw exception when trying to change level of language features to disable in multiplatform & fix tests
(cherry picked from commit 7d173ed385)
2019-07-22 11:40:09 +03:00
Dmitry Gridin
871cb5708d UpdateConfigurationQuickFixTest: update tests
(cherry picked from commit 0d49ffa831)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
76ebfd4f02 BuildScriptManipulator: implement new syntax for enable experimental features in MPP
#KT-28295 Fixed

(cherry picked from commit cb432acfb7)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
dc7763804d GradleConfiguratorTest: fix configureJvmEAPWithBuildGradleKts test
(cherry picked from commit 8887031962)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
e087fdff6c KotlinBuildScriptManipulator: cleanup code
(cherry picked from commit 46dfff7d82)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
13b87924ba FeatureSupportIntentionActionsFactory: add the missing branch else
(cherry picked from commit b1d1a4b2e1)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
a4f4199314 IDE: add warn on java files outside java source roots
#KT-28121 Fixed

(cherry picked from commit 60421c441e)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
19b3836b88 CreateExpectedFix: fix KNPE from init block
#KT-32639 Fixed

(cherry picked from commit 4928f3ff57)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
c49fedf84b CreateActualFix: should create source root directory if it doesn't exist
#KT-27555 Fixed

(cherry picked from commit fc45948da6)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
69d794591a RemoveRedundantQualifierNameInspection: shouldn't analysis import and package directives
(cherry picked from commit 229b8cb6a3)
2019-07-22 11:40:08 +03:00
Dmitry Gridin
10c0eedf9d RemoveRedundantQualifierNameInspection: fix false negative for java constructor
#KT-32506 Fixed

(cherry picked from commit 694c231689)
2019-07-22 11:40:07 +03:00
Anton Yalyshev
7fba7e299d Cleanup: specify description for Gradle Kotlin/Multiplatform wizard
(cherry picked from commit 959b720e3f)
2019-07-22 11:37:22 +03:00
Anton Yalyshev
25cf276591 Cleanup: make comments more informative
(cherry picked from commit 19dfbfa42c)
2019-07-22 11:37:22 +03:00
Anton Yalyshev
c0520b9f9d Extract adding of sourceSets to subclass, cause superclass is also used in other wizards where this procedure breaks build.gradle
#KT-32105 Fixed

(cherry picked from commit 1cdcde86e3)
2019-07-22 11:37:21 +03:00
Anton Yalyshev
f95e9f2057 Add clarifications about single/multi targeting to framework descriptions
(cherry picked from commit 5b66063650)
2019-07-22 11:37:21 +03:00
Anton Yalyshev
1d33d1bdc1 Refactoring: extract and pull up duplicated code from JVM- and JS- related subclassed
(cherry picked from commit a864715cb8)
2019-07-22 11:37:21 +03:00
Anton Yalyshev
90dbd3bc79 Add Kotlin/MPP to Gradle group of New Project Wizards #KT-32105 Fixed
(cherry picked from commit 9d6367a9be)
2019-07-22 11:37:21 +03:00
Dmitriy Dolovov
213611ee14 Make [Jvm|Js]IdePlatformKind and [Jvm|Js]IdePlatformKindTooling available in all IDEs
Issue #KT-29953 Fixed
2019-07-22 11:42:48 +07:00
Dmitriy Dolovov
a731b0e3ab Always analyze KTS with JVM platform
Issue #KT-29953
2019-07-22 11:42:41 +07:00
Dmitriy Dolovov
9087bdb244 CIDR: Filter aux library order entries that do not represent K/N libraries
Issue #KT-32726 Fixed
2019-07-22 11:42:34 +07:00
Vladimir Dolzhenko
c5626b7600 Fixed a corner case for invalidate package cache for default package
relates to KT-25264

(cherry picked from commit 0f6c381cd7)
2019-07-19 18:03:49 +02:00
Natalia Selezneva
7c52292b28 Invalid script dependencies should be removed from fileAttributes to avoid 'all red file highlighting'
^KT-32061 Fixed

(cherry picked from commit 7d6bb023a8)
2019-07-19 13:12:53 +03:00
Natalia Selezneva
02b4370132 Add Show Kotlin Gradle DSL Logs Action (KT-31440)
Provide a label for this action in some script diagnostics from gradle dsl resolver
^KT-31440 Fixed

(cherry picked from commit f6b03dc02f)
2019-07-19 13:12:52 +03:00
Natalia Selezneva
fef22e58c7 ScriptDefinitionsManager shouldn't be ready if definitions aren't initialized yet (KT-32554)
Otherwise this can lead to wrong script definition detection on project opening
^KT-32554 Fixed

(cherry picked from commit a2d284c769)
2019-07-19 13:12:51 +03:00
Natalia Selezneva
255dd2fa74 Scripts: pass script definition as parameter to loader (KT-32554)
This should avoid situation when script definition for file is changed between isApplicable and loadDependencies calls

^KT-32554 Fixed

(cherry picked from commit e40cdef257)
2019-07-19 13:12:50 +03:00
Natalia Selezneva
7aba6e36cb Scripts: check that file is non-script starting script compilation configuration update
Replace FileType check with more precise method isNonScript

(cherry picked from commit 763f1e8606)
2019-07-19 13:12:50 +03:00
Natalia Selezneva
87e7da4414 Append for commit: switch ScriptReportSink to new scripting API
Commit hash e4d0c2cb0e

(cherry picked from commit 4fed624942)
2019-07-19 13:12:49 +03:00
Natalia Selezneva
44fb1dd3e0 Performance: do not check file type for scripts with standard extension
(cherry picked from commit 63767b4dca)
2019-07-19 13:12:48 +03:00
Vladimir Dolzhenko
cdc165c019 Do not invalidate package caches on generic events, KT-25264
(cherry picked from commit 022275b781)
2019-07-19 10:16:10 +02:00
Vladimir Dolzhenko
0713dc3152 Show progress on remove unused imports, KT-30748
(cherry picked from commit 39f6416757)
2019-07-19 10:15:59 +02:00
victor.petukhov
3b87a770fb Add condition for checkNonParenthesizedAnnotationsOnFunctionalType call to except error reporting in stub mode
(cherry picked from commit 60c4eb68ff)
2019-07-19 11:02:51 +03:00
victor.petukhov
9d640362ee Fix error message for non-parenthesized annotations on functional types
(cherry picked from commit 7ee5583c89)
2019-07-19 11:02:24 +03:00
victor.petukhov
a15e286a44 Support non-parenthesized annotations on functional types without receiver
^KT-31734 Fixed

(cherry picked from commit 6a679d86ab)
2019-07-19 11:02:00 +03:00
Kirill Shmakov
5a82573452 Use same models in MPP and CIDR
(cherry picked from commit 407e5a5270)
2019-07-18 20:18:30 +03:00
nikita.movshin
b7b152f944 Update Kotlin Native version for EAP 2019-07-15 17:56:58 +03:00
Ivan Gavrilovic
d19fdb2008 KT-31291: Wrap ASM version in a method to avoid having it inlined
This commit adds a method to get the value of org.jetbrains.org.objectweb.asm.Oopcodes.API_VERSION.
In general, this should not be a problem, but some Gradle plugins package
Jetbrains ASM version. At runtime, their version may be loaded which may be
different than the one this code was compiled against.

(cherry picked from commit 4caddd2c1c)
2019-07-15 16:55:04 +09:00
Ivan Gavrilovic
4f27cc0efb Improve incremental KAPT logging
This commit improves incremental KAPT logging. It reports processor
stats using their actual names. Also, warning is printed if incremental
annotation processing is requested, but not all APs are incremental

(cherry picked from commit 6619106af2)
2019-07-15 16:54:54 +09:00
Ivan Gavrilovic
226bdfe993 KAPT: Mark incremental cache as LocalState
Use @LocalState to mark incremental annotation processing cache directory.
This is to make sure this is not stored in the build cache as it contains
absolute paths and cannot be shared between machines.

(cherry picked from commit 5cab6fd6cf)
2019-07-15 16:54:40 +09:00
Ivan Gavrilovic
293eb56a9f KT-31840: Fix caching for incremental annotation processing
Artifact transform that uses ASM to analyze KAPT classpath stored absolute
paths in the output artifact. This resulted in remote build cache misses.

This commit changes how analysis is stored. Actual analysis file is the
output of the transform, and there is not need to use a marker file any more.
Output does not store the classpath entry absolute path. Instead, it uses
task action incremental information to find analysis outputs that changed.

Additionally, class that handles analysis snapshot comparison has been
simplified, and lazy loading of the structural information is handled in
a more straightforward way.

(cherry picked from commit 251d8ccd97)
2019-07-15 16:54:29 +09:00
nikita.movshin
8442ecc368 Add changelog for 1.3.50 EAP 1 2019-07-13 15:12:08 +03:00
132 changed files with 13162 additions and 8943 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -182,7 +182,7 @@ extra["versions.trove4j"] = "1.0.20181211"
extra["versions.ktor-network"] = "1.0.1"
if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.3.50-dev-11052"
extra["versions.kotlin-native"] = "1.3.50-eap-11415"
}
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild

View File

@@ -23,6 +23,17 @@ if (flags.includeCidrPlugins) {
logger.info("NOT including CIDR plugins in buildSrc/settings.gradle")
}
if (flags.hasKotlinUltimate) {
logger.info("Including extension for IJ Ultimate in buildSrc/settings.gradle")
include ":prepare-deps:lldb-frontend"
include ":prepare-deps:native-debug-plugin"
project(":prepare-deps:lldb-frontend").projectDir = file("${flags.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-frontend")
project(":prepare-deps:native-debug-plugin").projectDir = file("${flags.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/native-debug-plugin")
} else {
logger.info("Not including extension for IJ Ultimate in buildSrc/settings.gradle")
}
class LocalBuildPropertiesProvider {
private Settings settings
private Properties localProperties = new Properties()
@@ -57,8 +68,11 @@ class LocalBuildProperties {
boolean includeCidrPlugins
boolean hasKotlinUltimate
LocalBuildProperties(Settings settings) {
propertiesProvider = new LocalBuildPropertiesProvider(settings)
includeCidrPlugins = propertiesProvider.getBoolean('cidrPluginsEnabled') && new File(propertiesProvider.rootProjectDir, 'kotlin-ultimate').exists()
hasKotlinUltimate = new File(propertiesProvider.rootProjectDir, 'kotlin-ultimate').exists()
includeCidrPlugins = propertiesProvider.getBoolean('cidrPluginsEnabled') && hasKotlinUltimate
}
}

View File

@@ -57,9 +57,7 @@ class KotlinBuildProperties(
val useBootstrapStdlib: Boolean
get() = isInJpsBuildIdeaSync || getBoolean("kotlin.build.useBootstrapStdlib", false)
val kotlinUltimateExists: Boolean = propertiesProvider.rootProjectDir.resolve("kotlin-ultimate").exists()
val includeCidrPlugins: Boolean = kotlinUltimateExists && getBoolean("cidrPluginsEnabled")
private val kotlinUltimateExists: Boolean = propertiesProvider.rootProjectDir.resolve("kotlin-ultimate").exists()
val isTeamcityBuild: Boolean = getBoolean("teamcity") || System.getenv("TEAMCITY_VERSION") != null
@@ -72,6 +70,10 @@ class KotlinBuildProperties(
return kotlinUltimateExists && (explicitlyEnabled || isTeamcityBuild)
}
val includeCidrPlugins: Boolean = kotlinUltimateExists && getBoolean("cidrPluginsEnabled")
val includeUltimate: Boolean = kotlinUltimateExists && (isTeamcityBuild || intellijUltimateEnabled)
val postProcessing: Boolean get() = isTeamcityBuild || getBoolean("kotlin.build.postprocessing", true)
val relocation: Boolean get() = postProcessing

View File

@@ -1159,6 +1159,34 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
}
}
@TestMetadata("compiler/testData/diagnostics/tests/annotations/functionalTypes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FunctionalTypes extends AbstractFirDiagnosticsSmokeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFunctionalTypes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/functionalTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("nonParenthesizedAnnotationsWithError.kt")
public void testNonParenthesizedAnnotationsWithError() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/nonParenthesizedAnnotationsWithError.kt");
}
@TestMetadata("nonParenthesizedAnnotationsWithoutError.kt")
public void testNonParenthesizedAnnotationsWithoutError() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/nonParenthesizedAnnotationsWithoutError.kt");
}
@TestMetadata("parenthesizedAnnotations.kt")
public void testParenthesizedAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/annotations/options")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)

View File

@@ -268,6 +268,8 @@ public interface Errors {
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES = DiagnosticFactory0.create(ERROR);
// Const
DiagnosticFactory0<PsiElement> CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> CONST_VAL_WITH_GETTER = DiagnosticFactory0.create(ERROR);

View File

@@ -159,6 +159,8 @@ public class DefaultErrorMessages {
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS, "Unsigned literals are experimental and their usages should be marked with ''@{0}'' or ''@UseExperimental({0}::class)''", TO_STRING);
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "Unsigned literals are experimental and their usages must be marked with ''@{0}'' or ''@UseExperimental({0}::class)''", TO_STRING);
MAP.put(NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES, "Non-parenthesized annotations on function types without receiver aren't yet supported (see KT-31734 for details)");
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");

View File

@@ -34,6 +34,9 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.resolve.PossiblyBareType.bare
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
@@ -69,6 +72,9 @@ class TypeResolver(
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
private val languageVersionSettings: LanguageVersionSettings
) {
private val isNonParenthesizedAnnotationsOnFunctionalTypesEnabled =
languageVersionSettings.getFeatureSupport(LanguageFeature.NonParenthesizedAnnotationsOnFunctionalTypes) == LanguageFeature.State.ENABLED
open class TypeTransformerForTests {
open fun transformType(kotlinType: KotlinType): KotlinType? = null
}
@@ -129,12 +135,54 @@ class TypeResolver(
internal fun KtElementImplStub<*>.getAllModifierLists(): Array<out KtDeclarationModifierList> =
getStubOrPsiChildren(KtStubElementTypes.MODIFIER_LIST, KtStubElementTypes.MODIFIER_LIST.arrayFactory)
// TODO: remove this method and its usages in 1.4
private fun checkNonParenthesizedAnnotationsOnFunctionalType(
typeElement: KtFunctionType,
annotationEntries: List<KtAnnotationEntry>,
trace: BindingTrace
) {
val lastAnnotationEntry = annotationEntries.lastOrNull()
val isAnnotationsGroupedUsingBrackets =
lastAnnotationEntry?.getNextSiblingIgnoringWhitespaceAndComments()?.node?.elementType == KtTokens.RBRACKET
val hasAnnotationParentheses = lastAnnotationEntry?.valueArgumentList != null
val isFunctionalTypeStartingWithParentheses = typeElement.firstChild is KtParameterList
val hasSuspendModifierBeforeParentheses =
typeElement.getPrevSiblingIgnoringWhitespaceAndComments().run { this is KtDeclarationModifierList && hasSuspendModifier() }
if (lastAnnotationEntry != null &&
isFunctionalTypeStartingWithParentheses &&
!hasAnnotationParentheses &&
!isAnnotationsGroupedUsingBrackets &&
!hasSuspendModifierBeforeParentheses
) {
trace.report(Errors.NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES.on(lastAnnotationEntry))
}
}
private fun resolveTypeAnnotations(c: TypeResolutionContext, modifierListsOwner: KtElementImplStub<*>): Annotations {
val modifierLists = modifierListsOwner.getAllModifierLists()
var result = Annotations.EMPTY
var isSplitModifierList = false
if (!isNonParenthesizedAnnotationsOnFunctionalTypesEnabled) {
val targetType = when (modifierListsOwner) {
is KtNullableType -> modifierListsOwner.innerType
is KtTypeReference -> modifierListsOwner.typeElement
else -> null
}
val annotationEntries = when (modifierListsOwner) {
is KtNullableType -> modifierListsOwner.modifierList?.annotationEntries
is KtTypeReference -> modifierListsOwner.annotationEntries
else -> null
}
// `targetType.stub == null` means that we don't apply this check for files that are built with stubs (that aren't opened in IDE and not in compile time)
if (targetType is KtFunctionType && targetType.stub == null && annotationEntries != null) {
checkNonParenthesizedAnnotationsOnFunctionalType(targetType, annotationEntries, c.trace)
}
}
for (modifierList in modifierLists) {
if (isSplitModifierList) {
c.trace.report(MODIFIER_LIST_NOT_ALLOWED.on(modifierList))

View File

@@ -509,24 +509,36 @@ public class KotlinParsing extends AbstractKotlinParsing {
}
private boolean parseTypeModifierList() {
return doParseModifierList(null, TYPE_MODIFIER_KEYWORDS, DEFAULT, TokenSet.EMPTY);
return doParseModifierList(null, TYPE_MODIFIER_KEYWORDS, TYPE_CONTEXT, TokenSet.EMPTY);
}
private boolean parseTypeArgumentModifierList() {
return doParseModifierList(null, TYPE_ARGUMENT_MODIFIER_KEYWORDS, NO_ANNOTATIONS, TokenSet.create(COMMA, COLON, GT));
}
private boolean doParseModifierList(
private boolean doParseModifierListBody(
@Nullable Consumer<IElementType> tokenConsumer,
@NotNull TokenSet modifierKeywords,
@NotNull AnnotationParsingMode annotationParsingMode,
@NotNull TokenSet noModifiersBefore
) {
PsiBuilder.Marker list = mark();
boolean empty = true;
PsiBuilder.Marker beforeAnnotationMarker;
while (!eof()) {
if (at(AT) && annotationParsingMode.allowAnnotations) {
parseAnnotationOrList(annotationParsingMode);
beforeAnnotationMarker = mark();
boolean isAnnotationParsed = parseAnnotationOrList(annotationParsingMode);
if (!isAnnotationParsed && !annotationParsingMode.withSignificantWhitespaceBeforeArguments) {
beforeAnnotationMarker.rollbackTo();
// try parse again, but with significant whitespace
doParseModifierListBody(tokenConsumer, modifierKeywords, WITH_SIGNIFICANT_WHITESPACE_BEFORE_ARGUMENTS, noModifiersBefore);
empty = false;
break;
} else {
beforeAnnotationMarker.drop();
}
}
else if (tryParseModifier(tokenConsumer, noModifiersBefore, modifierKeywords)) {
// modifier advanced
@@ -536,6 +548,25 @@ public class KotlinParsing extends AbstractKotlinParsing {
}
empty = false;
}
return empty;
}
private boolean doParseModifierList(
@Nullable Consumer<IElementType> tokenConsumer,
@NotNull TokenSet modifierKeywords,
@NotNull AnnotationParsingMode annotationParsingMode,
@NotNull TokenSet noModifiersBefore
) {
PsiBuilder.Marker list = mark();
boolean empty = doParseModifierListBody(
tokenConsumer,
modifierKeywords,
annotationParsingMode,
noModifiersBefore
);
if (empty) {
list.drop();
}
@@ -796,8 +827,27 @@ public class KotlinParsing extends AbstractKotlinParsing {
parseTypeArgumentList();
if (at(LPAR)) {
boolean whitespaceAfterAnnotation = WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(-1));
boolean shouldBeParsedNextAsFunctionalType = at(LPAR) && whitespaceAfterAnnotation && mode.withSignificantWhitespaceBeforeArguments;
if (at(LPAR) && !shouldBeParsedNextAsFunctionalType) {
myExpressionParsing.parseValueArgumentList();
/*
* There are two problem cases relating to parsing of annotations on a functional type:
* - Annotation on a functional type was parsed correctly with the capture parentheses of the functional type,
* e.g. @Anno () -> Unit
* ^ Parse error only here: Type expected
* - It wasn't parsed, e.g. @Anno (x: kotlin.Any) -> Unit
* ^ Parse error: Expecting ')'
*
* In both cases, parser should rollback to start parsing of annotation and tries parse it with significant whitespace.
* A marker is set here which means that we must to rollback.
*/
if (mode.typeContext && (getLastToken() != RPAR || at(ARROW))) {
annotation.done(ANNOTATION_ENTRY);
return false;
}
}
annotation.done(ANNOTATION_ENTRY);
@@ -1995,7 +2045,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
else if (at(LPAR)) {
PsiBuilder.Marker functionOrParenthesizedType = mark();
// This may be a function parameter list or just a prenthesized type
// This may be a function parameter list or just a parenthesized type
advance(); // LPAR
parseTypeRefContents(TokenSet.EMPTY).drop(); // parenthesized types, no reference element around it is needed
@@ -2423,20 +2473,28 @@ public class KotlinParsing extends AbstractKotlinParsing {
}
enum AnnotationParsingMode {
DEFAULT(false, true),
FILE_ANNOTATIONS_BEFORE_PACKAGE(true, true),
FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED(true, true),
NO_ANNOTATIONS(false, false);
DEFAULT(false, true, false, false),
FILE_ANNOTATIONS_BEFORE_PACKAGE(true, true, false, false),
FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED(true, true, false, false),
TYPE_CONTEXT(false, true, true, false),
WITH_SIGNIFICANT_WHITESPACE_BEFORE_ARGUMENTS(false, true, true, true),
NO_ANNOTATIONS(false, false, false, false);
boolean isFileAnnotationParsingMode;
boolean allowAnnotations;
boolean withSignificantWhitespaceBeforeArguments;
boolean typeContext;
AnnotationParsingMode(
boolean isFileAnnotationParsingMode,
boolean allowAnnotations
boolean allowAnnotations,
boolean typeContext,
boolean withSignificantWhitespaceBeforeArguments
) {
this.isFileAnnotationParsingMode = isFileAnnotationParsingMode;
this.allowAnnotations = allowAnnotations;
this.typeContext = typeContext;
this.withSignificantWhitespaceBeforeArguments = withSignificantWhitespaceBeforeArguments;
}
}
}

View File

@@ -0,0 +1,70 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -CAST_NEVER_SUCCEEDS -CANNOT_CHECK_FOR_ERASED -UNCHECKED_CAST -UNUSED_ANONYMOUS_PARAMETER
// SKIP_TXT
// Issue: KT-31734
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
@Repeatable
annotation class Foo
fun foo1(x: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit) = x as Iterable<<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit>?
fun foo2() = null as <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit
fun foo3(x: Any?) {
if (x is (<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>Foo<!><!> () -> Unit)?) {
}
}
fun foo4(x: Any) = x is <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> (() -> Unit?)
fun foo5(x: Any): <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit = x as @Foo() @[Foo Foo()] <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit
fun foo6() {
val x: @Foo() @[Foo Foo()] <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit = {}
}
fun foo7() {
val x: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> (<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit) -> Unit = { x: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit -> }
}
fun foo8(<!UNUSED_PARAMETER!>x<!>: Any?) {
val <!NAME_SHADOWING!>x<!>: (<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit)? = {}
}
fun foo9(x: (<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit)?) = x as Iterable<(<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit?)?>?
fun foo10(x: @[Foo] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo11(x: @[Foo ] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo12(x: @[Foo/**/] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
val foo13: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> (x: @Foo Any) -> Unit get() = {}
val foo14: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> (x: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit) -> Unit get() = {}
val foo15: @Foo () <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit get() = {}
val foo16: @Foo @Foo () <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit get() = {}
val foo17: @Foo() @Foo () <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit get() = {}
val foo18: @Foo()@Foo () <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit get() = {}
val foo19: @Foo@Foo () <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit get() = {}
val foo20: @Foo<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit get() = {}
val foo21: @Foo()<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit get() = {}
val foo22: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> (x: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit) -> Unit get() = {}
val foo23: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> (<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit) -> Unit get() = {}
val foo24: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> (<!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit, <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> () -> Unit) -> Unit get() = {x, y -> }
val foo25: <!NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES!>@Foo<!> (x: @Foo Any, @Foo Any) -> Unit get() = {x, y -> }
val foo26: @Foo suspend () -> Unit = {}

View File

@@ -0,0 +1,67 @@
// !LANGUAGE: +NonParenthesizedAnnotationsOnFunctionalTypes
// !DIAGNOSTICS: -UNUSED_VARIABLE -CAST_NEVER_SUCCEEDS -CANNOT_CHECK_FOR_ERASED -UNCHECKED_CAST -UNUSED_ANONYMOUS_PARAMETER
// SKIP_TXT
// Issue: KT-31734
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
@Repeatable
annotation class Foo
class MyClass
fun foo1(x: @Foo () -> Unit) = x as Iterable<@Foo () -> Unit>?
fun foo2() = null as @Foo () -> Unit
fun foo3(x: Any?) {
if (x is (@<!DEBUG_INFO_MISSING_UNRESOLVED!>Foo<!> () -> Unit)?) {
}
}
fun foo4(x: Any) = x is @Foo () -> (() -> Unit?)
fun foo5(x: Any): @Foo () -> Unit = x as @Foo() @[Foo Foo()] @Foo () -> Unit
fun foo6() {
val x: @Foo() @[Foo Foo()] @Foo () -> Unit = {}
}
fun foo7() {
val x: @Foo (@Foo () -> Unit) -> Unit = { x: @Foo () -> Unit -> }
}
fun foo10(x: @[Foo()] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo11(x: @[Foo] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo12(x: @[Foo ] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo13(x: @[Foo/**/] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
val foo14: @Foo (x: @Foo () -> Unit) -> Unit get() = {}
val foo15: @Foo () @Foo () -> Unit get() = {}
val foo16: @Foo @Foo () @Foo () -> Unit get() = {}
val foo17: @Foo() @Foo () @Foo () -> Unit get() = {}
val foo18: @Foo()@Foo () @Foo () -> Unit get() = {}
val foo19: @Foo@Foo () @Foo () -> Unit get() = {}
val foo20: @Foo@Foo () -> Unit get() = {}
val foo21: @Foo()@Foo () -> Unit get() = {}
val foo22: @Foo (x: @Foo () -> Unit) -> Unit get() = {}
val foo23: @Foo (@Foo () -> Unit) -> Unit get() = {}
val foo24: @Foo (@Foo () -> Unit, @Foo () -> Unit) -> Unit get() = {x, y -> }
val foo25: @Foo (x: @Foo Any, @Foo Any) -> Unit get() = {x, y -> }
val foo26: @Foo suspend () -> Unit = {}

View File

@@ -0,0 +1,46 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -CAST_NEVER_SUCCEEDS -CANNOT_CHECK_FOR_ERASED -UNCHECKED_CAST -UNUSED_ANONYMOUS_PARAMETER
// SKIP_TXT
// Issue: KT-31734
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
@Repeatable
annotation class Foo
fun foo1(x: @Foo() () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo2() = null as @Foo() () -> Unit
fun foo3(x: Any?) {
if (x is (@<!DEBUG_INFO_MISSING_UNRESOLVED!>Foo<!>() () -> Unit)?) {
}
}
fun foo4(x: Any) = x is @Foo() () -> (() -> Unit?)
fun foo5(x: Any): @Foo() () -> Unit = x as @Foo () @[Foo Foo ()] @Foo() () -> Unit
fun foo6() {
val x: @Foo() @[Foo Foo()] @Foo() () -> Unit = {}
}
fun foo7() {
val x: @Foo() (@Foo() () -> Unit) -> Unit = { x: @Foo() () -> Unit -> }
}
fun foo8(x: @[Foo() ] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo9(x: @[Foo()] () -> Unit) = x as Iterable<@Foo() () -> Unit>?
fun foo10() {
val x: @Foo () @Foo () () -> Unit = {}
}
fun foo11() {
val x: @Foo @Foo () () -> Unit = {}
}
fun foo12() {
val x: @Foo() @Foo () () -> Unit = {}
}

View File

@@ -0,0 +1,11 @@
// Issue: KT-31734
fun foo() {
for (@Foo (i: Int) in y) {}
for (@Foo (i: () -> Unit) in y) {}
for (@Foo (i) in y) {}
for (@Foo (i, j) in y) {}
for (@Foo (i, j: Int) in y) {}
for (@Foo i: Int in y) {}
for (@Foo i in y) {}
}

View File

@@ -0,0 +1,282 @@
KtFile: forDestructuring.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
PsiComment(EOL_COMMENT)('// Issue: KT-31734')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiErrorElement:Unexpected type specification
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Int')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(in)('in')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiErrorElement:Expecting 'in'
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiErrorElement:Expecting ')'
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
DESTRUCTURING_DECLARATION
PsiElement(LPAR)('(')
PsiErrorElement:Expecting a name
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting 'in'
PsiElement(ARROW)('->')
PsiErrorElement:Expecting ')'
<empty list>
PsiWhiteSpace(' ')
BODY
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Unit')
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(in)('in')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
BLOCK
<empty list>
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(in)('in')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiErrorElement:Expecting 'in'
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('j')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(in)('in')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiErrorElement:Expecting 'in'
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('j')
PsiErrorElement:Unexpected type specification
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Int')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(in)('in')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiErrorElement:Expecting 'in'
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('i')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PsiElement(in)('in')
PsiWhiteSpace(' ')
LOOP_RANGE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('y')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('i')
PsiWhiteSpace(' ')
PsiElement(in)('in')
PsiWhiteSpace(' ')
LOOP_RANGE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('y')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')

View File

@@ -0,0 +1,9 @@
// Issue: KT-31734
fun foo() {
val x = { @Foo (foo, bar) -> }
val x = { @Foo (foo: kotlin.Any, bar) -> }
val x = { @Foo (foo, bar: Any) -> }
val x = { @Foo ((foo, bar: Any)) -> }
val x = { @Foo () -> Unit }
}

View File

@@ -0,0 +1,230 @@
KtFile: lambdaParameterDeclaration.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
PsiComment(EOL_COMMENT)('// Issue: KT-31734')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
BLOCK
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(ARROW)('->')
PsiWhiteSpace(' ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
BLOCK
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiErrorElement:Unexpected type specification
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('kotlin')
PsiErrorElement:Expecting ')'
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Any')
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('bar')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(ARROW)('->')
PsiWhiteSpace(' ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
BLOCK
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiErrorElement:Unexpected type specification
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Any')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(ARROW)('->')
PsiWhiteSpace(' ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
BLOCK
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
PARENTHESIZED
PsiElement(LPAR)('(')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiErrorElement:Expecting ')'
<empty list>
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiErrorElement:Unexpected type specification
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Any')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting an element
<empty list>
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(ARROW)('->')
PsiWhiteSpace(' ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
BLOCK
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(ARROW)('->')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Unit')
PsiWhiteSpace(' ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')

View File

@@ -0,0 +1,9 @@
// Issue: KT-31734
fun foo() {
val @Foo (i) = Pair(1, 2)
var @Foo (i: () -> Unit) = Pair(1, 2)
var @Foo (i: Int) = Pair(1, 2)
val @Foo (i, j) = Pair(1, 2)
val @Foo (i, j: Int) = Pair(1, 2)
}

View File

@@ -0,0 +1,230 @@
KtFile: variableDestructuring.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
PsiComment(EOL_COMMENT)('// Issue: KT-31734')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiErrorElement:Annotations are not allowed in this position
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting property name or receiver type
<empty list>
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Pair')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
DESTRUCTURING_DECLARATION
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiErrorElement:Annotations are not allowed in this position
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiErrorElement:Expecting ')'
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
PsiErrorElement:Expecting a name
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(ARROW)('->')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Unit')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Pair')
PsiElement(LPAR)('(')
PsiElement(INTEGER_LITERAL)('1')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
PsiElement(INTEGER_LITERAL)('2')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiErrorElement:Annotations are not allowed in this position
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiErrorElement:Unexpected type specification
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Int')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting property name or receiver type
<empty list>
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Pair')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiErrorElement:Annotations are not allowed in this position
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('j')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting property name or receiver type
<empty list>
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Pair')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiErrorElement:Annotations are not allowed in this position
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('i')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('j')
PsiErrorElement:Unexpected type specification
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Int')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting property name or receiver type
<empty list>
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Pair')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')

View File

@@ -0,0 +1,47 @@
// Issue: KT-31734
val x: (@Foo(10) suspend (Int) -> Unit) get() = {}
val x: @Foo({}) ((x: @Foo(10) (@Foo(11) () -> Int) -> Int) -> Unit) get() = {}
val x: suspend @Foo(10) (x: @Foo(10) (@Foo("") (x: kotlin.Any) -> Int) -> Int) -> Unit get() = {}
val x: Comparable<@Foo(10) @Bar(10) @Foo(listOf(10)) (x: kotlin.Any = {}) -> Unit> get() = {}
val x: Any = {} as @Foo({ x: Int -> 10}) suspend (x: @Foo(10) Foo) -> (y: @Foo(10) Bar) -> Unit
fun foo(x: (@Foo(10) (@Foo({ x: Int -> 10}) kotlin.Any)->()->Unit)) = x
fun foo(x: suspend @Foo(10) @Bar(10 + @Foo 3) (kotlin.Any) -> Unit = { x: Int -> x }) {}
fun foo() {
val x: @Foo(10) suspend @Bar(throw Exception()) (Coomparable<kotlin.Any>) -> Unit = {}
}
fun foo() {
val x = { x: suspend @Foo(null) (Coomparable<@Foo(10) @Bar(10) @Foo(10) () -> Unit>) -> () -> Unit -> x }
}
abstract class A {
abstract var x: @Foo(10 as @Foo suspend (Int) -> ((Int) -> Unit)) suspend (suspend (Int) -> ((Int) -> Unit)) -> Int
}
fun foo(vararg x: @Foo(10) @Bar(10) @Foo(Any) (Any) -> Unit) = 10
fun foo(): @Foo.Bar(@Foo x) suspend (Nothing) -> Unit = {}
fun foo(): () -> @Foo.Bar('1') suspend (Bar) -> Unit = {}
val x: Any get() = fun(): @Foo("") (Coomparable<Nothing>) -> Unit {}
fun foo() {
var x: (@Foo(object {}) (()->Unit)-> ()->Unit) -> Unit = {}
}
fun foo(x: Any) {
if (x as @Foo({}) @Bar(10) @Foo(10) (()->Unit) -> Unit is suspend @Foo(10) @Bar(10) @Foo(10) (()->Unit) -> Unit) {}
}
fun foo(y: Any) {
var x = y as (@Foo({}) suspend (()->Unit) -> (()->Unit) -> Unit) -> Unit
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
// Issue: KT-31734
val x: (@Foo() () -> Unit) get() = {}
val x: @Foo() (() -> Unit) get() = {}
val x: @Foo() () -> Unit get() = {}
val x: Comparable<@Fo() @Bar(10) @Foo() () -> Unit> get() = {}
val x: Any = {} as @Foo() () -> Unit
fun foo(x: (@Foo() () -> Unit)) = x
fun foo(x: @Foo(10) @Bar() () -> Unit = { x: Int -> x }) {}
fun foo() {
val x: @Foo() @Bar() () -> Unit = {}
}
fun foo() {
val x = { x: @Foo() () -> () -> Unit -> x }
}
abstract class A {
abstract var x: @Foo() (() -> (() -> Unit)) -> Int
}
fun foo(vararg x: @Foo() @Bar(10) @Foo() () -> Unit) = 10
fun foo(): @Foo.Bar() () -> Unit = {}
fun foo(): () -> @Foo.Bar() () -> Unit = {}
val x: Any get() = fun(): @Foo() () -> Unit {}
fun foo() {
var x: (@Foo() ()->()->Unit) -> Unit = {}
}
fun foo(x: Any) {
if (x as @Foo() @Bar(10) @Foo() () -> Unit is @Foo() @Bar(10) @Foo() () -> Unit) {}
}
fun foo(y: Any) {
var x = y as (@Foo() () -> () -> Unit) -> Unit
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
// Issue: KT-31734
val x: (@[Foo] suspend (Int) -> Unit) get() = {}
val x: (@[Foo] () -> Unit) get() = {}
val x: (@[Foo] suspend () -> Unit) get() = {}
val x: @[Foo] ((x: @[Foo] (@[Foo Foo] () -> Int) -> Int) -> Unit) get() = {}
val x: suspend @[Foo] (x: @[Foo Foo] (@[Foo Foo] (x: kotlin.Any) -> Int) -> Int) -> Unit get() = {}
val x: Comparable<@[Foo] @[Bar(10)] @[Foo] () -> Unit> get() = {}
val x: Any = {} as @[Foo Foo] suspend (x: @[Foo] Foo) -> (y: @[Foo] Bar) -> Unit
fun foo(x: (@Foo ()->()->Unit)) = x
fun foo(x: suspend @[Foo Foo(10)] @[Bar] (kotlin.Any) -> Unit = { x: Int -> x }) {}
fun foo() {
val x: @[Foo(10)] @[Bar] (Coomparable<kotlin.Any>) -> Unit = {}
}
fun foo() {
val x = { x: suspend @[Foo Bar] (Coomparable<@[Foo Bar Bar Bar Bar Bar] @[Bar(10)] @[Foo Bar] () -> Unit>) -> () -> Unit -> x }
}
abstract class A {
abstract var x: @[Foo Bar] suspend (() -> ((Int) -> Unit)) -> Int
}
fun foo(vararg x: @[Foo Bar] @[Bar(10)] @[Foo Bar] () -> Unit) = 10
fun foo(): @[Foo.Bar Foo.Bar(1)] suspend () -> Unit = {}
fun foo(): () -> @[Foo.Bar] () -> Unit = {}
val x: Any get() = fun(): @[Foo()] (Coomparable<Nothing>) -> Unit {}
fun foo() {
var x: (@[Foo Bar] (()->Unit)-> ()->Unit) -> Unit = {}
}
fun foo(x: Any) {
if (x as @[Foo] @[Bar(10) Bar] @[Foo Bar] (()->Unit) -> Unit is suspend @[Foo] @[Bar (10)] @[Foo Bar (10)] (()->Unit) -> Unit) {}
}
fun foo(y: Any) {
var x = y as (@[Foo Bar] suspend (()->Unit) -> (()->Unit) -> Unit) -> Unit
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
// Issue: KT-31734
val x: (@Foo suspend (Int) -> Unit) get() = {}
val x: @Foo ((x: @Foo (@Foo () -> Int) -> Int) -> Unit) get() = {}
val x: suspend @Foo (x: @Foo (@Foo (x: kotlin.Any) -> Int) -> Int) -> Unit get() = {}
val x: Comparable<@Foo @Bar(10) @Foo (x: kotlin.Any = {}) -> Unit> get() = {}
val x: Any = {} as @Foo suspend (x: @Foo Foo) -> (y: @Foo Bar) -> Unit
fun foo(x: (@Foo (@Foo kotlin.Any)->()->Unit)) = x
fun foo(x: suspend @Foo(10) @Bar (kotlin.Any) -> Unit = { x: Int -> x }) {}
fun foo() {
val x: @Foo suspend @Bar (Coomparable<kotlin.Any>) -> Unit = {}
}
fun foo() {
val x = { x: suspend @Foo (Coomparable<@Foo @Bar(10) @Foo () -> Unit>) -> () -> Unit -> x }
}
abstract class A {
abstract var x: @Foo suspend (suspend (Int) -> ((Int) -> Unit)) -> Int
}
fun foo(vararg x: @Foo @Bar(10) @Foo (Any) -> Unit) = 10
fun foo(): @Foo.Bar suspend (Nothing) -> Unit = {}
fun foo(): () -> @Foo.Bar suspend (Bar) -> Unit = {}
val x: Any get() = fun(): @Foo (Coomparable<Nothing>) -> Unit {}
fun foo() {
var x: (@Foo (()->Unit)-> ()->Unit) -> Unit = {}
}
fun foo(x: Any) {
if (x as @Foo @Bar(10) @Foo (()->Unit) -> Unit is suspend @Foo @Bar(10) @Foo (()->Unit) -> Unit) {}
}
fun foo(y: Any) {
var x = y as (@Foo suspend (()->Unit) -> (()->Unit) -> Unit) -> Unit
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
// Issue: KT-31734
val x: (@Foo suspend Int.() -> Unit) get() = {}
val x: @Foo Int.() -> Unit get() = {}
val x: @Foo Int.(x: kotlin.Int) -> Unit get() = {}
val x: @Foo ((x: @Foo (@Foo () -> Int) -> Int.(@Foo () -> Int) -> Int) -> Unit) get() = {}
val x: suspend @Foo (x: @Foo (@Foo ((x: kotlin.Any) -> Int).(x: kotlin.Any) -> Int) -> Int) -> Unit get() = {}
val x: Comparable<@Foo @Bar(10) @Foo Unit.(x: kotlin.Any = {}) -> Unit> get() = {}
val x: Any = {} as @Foo suspend Int.(x: @Foo Foo) -> (y: @Foo Bar) -> Unit
fun foo(x: (@Foo ((@Foo kotlin.Any)->(Int)).(@Foo kotlin.Any)->()->Unit)) = x
fun foo(x: suspend @Foo(10) @Bar Comparable<T>.(kotlin.Any) -> Unit = { x: Int -> x }) {}
fun foo() {
val x: @Foo suspend @Bar (Coomparable<kotlin.Any>) -> Unit.(Coomparable<kotlin.Any>) -> Unit = {}
}
fun foo() {
val x = { x: suspend @Foo @Foo () -> Unit.(Coomparable<@Foo @Bar(10) @Foo () -> Unit>) -> () -> Unit -> x }
}
abstract class A {
abstract var x: @Foo suspend (@Foo () -> Unit).(suspend (Int) -> ((Int) -> Unit)) -> Int
}
fun foo(vararg x: @Foo @Bar(10) @Foo Any.(Any) -> Unit) = 10
fun foo(): @Foo.Bar suspend Nothing.(Nothing) -> Unit = {}
fun foo(): () -> @Foo.Bar suspend Iterable<@Foo.Bar Int.(Bar) -> Unit>.(Bar) -> Unit = {}
val x: Any get() = fun(): @Foo (@Foo (Coomparable<Nothing>) -> Unit).(Coomparable<Nothing>) -> Unit {}
fun foo() {
var x: (@Foo (()->Unit)-> @Foo Int.()->Unit) -> Unit = {}
}
fun foo(x: Any) {
if (x as @Foo @Bar(10) @Foo ()->Unit.(()->Unit) -> Unit is suspend @Foo @Bar(10) @Foo ((()->Unit).()->Unit) -> Unit) {}
}
fun foo(y: Any) {
var x = y as (@Foo suspend (suspend (()->Unit)->Int).(()->Unit) -> (Float.()->Unit) -> Unit) -> Unit
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
// Issue: KT-31734
val x: (@Foo () -> Unit) get() = {}
val x: @Foo (() -> Unit) get() = {}
val x: @Foo () -> Unit get() = {}
val x: Comparable<@Foo @Bar(10) @Foo () -> Unit> get() = {}
val x: Any = {} as @Foo () -> Unit
fun foo(x: (@Foo () -> Unit)) = x
fun foo(x: @Foo(10) @Bar () -> Unit = { x: Int -> x }) {}
fun foo() {
val x: @Foo @Bar () -> Unit = {}
}
fun foo() {
val x = { x: @Foo () -> () -> Unit -> x }
}
abstract class A {
abstract var x: @Foo (() -> (() -> Unit)) -> Int
}
fun foo(vararg x: @Foo @Bar(10) @Foo () -> Unit) = 10
fun foo(): @Foo.Bar () -> Unit = {}
fun foo(): () -> @Foo.Bar () -> Unit = {}
val x: Any get() = fun(): @Foo () -> Unit {}
fun foo() {
var x: (@Foo ()->()->Unit) -> Unit = {}
}
fun foo(x: Any) {
if (x as @Foo @Bar(10) @Foo () -> Unit is @Foo @Bar(10) @Foo () -> Unit) {}
}
fun foo(y: Any) {
var x = y as (@Foo () -> () -> Unit) -> Unit
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
// Issue: KT-31734
val x: (@Foo suspend () -> Unit) get() = {}
val x: @Foo (suspend () -> Unit) get() = {}
val x: suspend @Foo () -> Unit get() = {}
val x: Comparable<@Foo suspend @Bar(10) @Foo () -> Unit> get() = {}
val x: Any = {} as @Foo suspend () -> Unit
fun foo(x: (suspend @Foo () -> Unit)) = x
fun foo(x: suspend @Foo(10) @Bar () -> Unit = { x: Int -> x }) {}
fun foo() {
val x: @Foo suspend @Bar () -> Unit = {}
}
fun foo() {
val x = { x: suspend @Foo () -> () -> Unit -> x }
}
abstract class A {
abstract var x: @Foo suspend (suspend () -> (() -> Unit)) -> Int
}
fun foo(vararg x: @Foo @Bar(10) @Foo () -> Unit) = 10
fun foo(): @Foo.Bar suspend () -> Unit = {}
fun foo(): () -> @Foo.Bar suspend () -> Unit = {}
val x: Any get() = fun(): @Foo suspend () -> Unit {}
fun foo() {
var x: (@Foo ()->suspend ()->Unit) -> Unit = {}
}
fun foo(x: Any) {
if (x as @Foo @Bar(10) suspend @Foo () -> Unit is suspend @Foo @Bar(10) @Foo () -> Unit) {}
}
fun foo(y: Any) {
var x = y as (@Foo suspend () -> () -> Unit) -> Unit
}

View File

@@ -1166,6 +1166,34 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
}
}
@TestMetadata("compiler/testData/diagnostics/tests/annotations/functionalTypes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FunctionalTypes extends AbstractDiagnosticsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFunctionalTypes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/functionalTypes"), Pattern.compile("^(.*)\\.kts?$"), TargetBackend.ANY, true);
}
@TestMetadata("nonParenthesizedAnnotationsWithError.kt")
public void testNonParenthesizedAnnotationsWithError() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/nonParenthesizedAnnotationsWithError.kt");
}
@TestMetadata("nonParenthesizedAnnotationsWithoutError.kt")
public void testNonParenthesizedAnnotationsWithoutError() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/nonParenthesizedAnnotationsWithoutError.kt");
}
@TestMetadata("parenthesizedAnnotations.kt")
public void testParenthesizedAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/annotations/options")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)

View File

@@ -1161,6 +1161,34 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
}
}
@TestMetadata("compiler/testData/diagnostics/tests/annotations/functionalTypes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FunctionalTypes extends AbstractDiagnosticsUsingJavacTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFunctionalTypes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/functionalTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("nonParenthesizedAnnotationsWithError.kt")
public void testNonParenthesizedAnnotationsWithError() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/nonParenthesizedAnnotationsWithError.kt");
}
@TestMetadata("nonParenthesizedAnnotationsWithoutError.kt")
public void testNonParenthesizedAnnotationsWithoutError() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/nonParenthesizedAnnotationsWithoutError.kt");
}
@TestMetadata("parenthesizedAnnotations.kt")
public void testParenthesizedAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/annotations/options")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)

View File

@@ -901,6 +901,108 @@ public class ParsingTestGenerated extends AbstractParsingTest {
}
}
@TestMetadata("compiler/testData/psi/annotation/functionalTypes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FunctionalTypes extends AbstractParsingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doParsingTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFunctionalTypes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/functionalTypes"), Pattern.compile("^(.*)\\.kts?$"), TargetBackend.ANY, true);
}
@TestMetadata("compiler/testData/psi/annotation/functionalTypes/regressionForSimilarSyntax")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class RegressionForSimilarSyntax extends AbstractParsingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doParsingTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInRegressionForSimilarSyntax() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/functionalTypes/regressionForSimilarSyntax"), Pattern.compile("^(.*)\\.kts?$"), TargetBackend.ANY, true);
}
@TestMetadata("forDestructuring.kt")
public void testForDestructuring() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/regressionForSimilarSyntax/forDestructuring.kt");
}
@TestMetadata("lambdaParameterDeclaration.kt")
public void testLambdaParameterDeclaration() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/regressionForSimilarSyntax/lambdaParameterDeclaration.kt");
}
@TestMetadata("variableDestructuring.kt")
public void testVariableDestructuring() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/regressionForSimilarSyntax/variableDestructuring.kt");
}
}
@TestMetadata("compiler/testData/psi/annotation/functionalTypes/withParentheses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class WithParentheses extends AbstractParsingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doParsingTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInWithParentheses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/functionalTypes/withParentheses"), Pattern.compile("^(.*)\\.kts?$"), TargetBackend.ANY, true);
}
@TestMetadata("withParameter.kt")
public void testWithParameter() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/withParentheses/withParameter.kt");
}
@TestMetadata("withoutParameter.kt")
public void testWithoutParameter() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/withParentheses/withoutParameter.kt");
}
}
@TestMetadata("compiler/testData/psi/annotation/functionalTypes/withoutParentheses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class WithoutParentheses extends AbstractParsingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doParsingTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInWithoutParentheses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/functionalTypes/withoutParentheses"), Pattern.compile("^(.*)\\.kts?$"), TargetBackend.ANY, true);
}
@TestMetadata("annotationList.kt")
public void testAnnotationList() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/withoutParentheses/annotationList.kt");
}
@TestMetadata("withParameter.kt")
public void testWithParameter() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/withoutParentheses/withParameter.kt");
}
@TestMetadata("withReveiver.kt")
public void testWithReveiver() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/withoutParentheses/withReveiver.kt");
}
@TestMetadata("withoutParameter.kt")
public void testWithoutParameter() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/withoutParentheses/withoutParameter.kt");
}
@TestMetadata("withoutParameterOnSuspend.kt")
public void testWithoutParameterOnSuspend() throws Exception {
runTest("compiler/testData/psi/annotation/functionalTypes/withoutParentheses/withoutParameterOnSuspend.kt");
}
}
}
@TestMetadata("compiler/testData/psi/annotation/list")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)

View File

@@ -102,6 +102,7 @@ enum class LanguageFeature(
ProhibitUseSiteTargetAnnotationsOnSuperTypes(KOTLIN_1_4, kind = BUG_FIX),
ProhibitTypeParametersInClassLiteralsInAnnotationArguments(KOTLIN_1_4, kind = BUG_FIX),
ProhibitComparisonOfIncompatibleEnums(KOTLIN_1_4, kind = BUG_FIX),
NonParenthesizedAnnotationsOnFunctionalTypes(KOTLIN_1_4),
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
// Temporarily disabled, see KT-27084/KT-22379

View File

@@ -924,7 +924,7 @@ fun main(args: Array<String>) {
}
testClass<AbstractCompletionCharFilterTest> {
model("handlers/charFilter")
model("handlers/charFilter", pattern = KT_WITHOUT_DOTS_IN_NAME)
}
testClass<AbstractMultiFileJvmBasicCompletionTest> {
@@ -1219,7 +1219,7 @@ fun main(args: Array<String>) {
}
testClass<AbstractPerformanceCompletionCharFilterTest> {
model("handlers/charFilter", testMethod = "doPerfTest")
model("handlers/charFilter", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME)
}
}
/*

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.idea.caches
import com.intellij.ProjectTopics
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
@@ -87,7 +86,7 @@ class KotlinPackageContentModificationListener(private val project: Project) {
class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Project) : PsiTreeChangePreprocessor {
override fun treeChanged(event: PsiTreeChangeEventImpl) {
val eFile = event.file ?: event.child as? PsiFile
if (eFile == null) LOG.debugIfEnabled(project, "Got PsiEvent: $event without file", true)
if (eFile == null) LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without file" }
val file = eFile as? KtFile ?: return
when (event.code) {
@@ -96,7 +95,7 @@ class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Proje
PsiTreeChangeEventImpl.PsiEventType.CHILD_REPLACED,
PsiTreeChangeEventImpl.PsiEventType.CHILD_REMOVED -> {
val child = event.child ?: run {
LOG.debugIfEnabled(project, "Got PsiEvent: $event without child", true)
LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without child" }
return
}
if (child.getParentOfType<KtPackageDirective>(false) != null)
@@ -104,10 +103,13 @@ class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Proje
}
PsiTreeChangeEventImpl.PsiEventType.CHILDREN_CHANGED -> {
val parent = event.parent ?: run {
LOG.debugIfEnabled(project, "Got PsiEvent: $event without parent", true)
LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without parent" }
return
}
if (parent.getChildrenOfType<KtPackageDirective>().any())
val childrenOfType = parent.getChildrenOfType<KtPackageDirective>()
if ((!event.isGenericChange && (childrenOfType.any() || parent is KtPackageDirective)) ||
(childrenOfType.any { it.name.isEmpty() } && parent is KtFile)
)
ServiceManager.getService(project, PerModulePackageCacheService::class.java).notifyPackageChange(file)
}
else -> {
@@ -244,7 +246,7 @@ class PerModulePackageCacheService(private val project: Project) {
}
private fun invalidateCacheForModuleSourceInfo(moduleSourceInfo: ModuleSourceInfo) {
LOG.debugIfEnabled(project, "Invalidated cache for $moduleSourceInfo", false)
LOG.debugIfEnabled(project) { "Invalidated cache for $moduleSourceInfo" }
val perSourceInfoData = cache[moduleSourceInfo.module] ?: return
val dataForSourceInfo = perSourceInfoData[moduleSourceInfo] ?: return
dataForSourceInfo.clear()
@@ -264,14 +266,14 @@ class PerModulePackageCacheService(private val project: Project) {
if (sourceRootUrls.any { url ->
vfile.containedInOrContains(url)
}) {
LOG.debugIfEnabled(project, "Invalidated cache for $module")
LOG.debugIfEnabled(project) { "Invalidated cache for $module" }
data.clear()
}
}
} else {
val infoByVirtualFile = getModuleInfoByVirtualFile(project, vfile)
if (infoByVirtualFile == null || infoByVirtualFile !is ModuleSourceInfo) {
LOG.debugIfEnabled(project, "Skip $vfile as it has mismatched ModuleInfo=$infoByVirtualFile")
LOG.debugIfEnabled(project) { "Skip $vfile as it has mismatched ModuleInfo=$infoByVirtualFile" }
}
(infoByVirtualFile as? ModuleSourceInfo)?.let {
invalidateCacheForModuleSourceInfo(it)
@@ -283,13 +285,13 @@ class PerModulePackageCacheService(private val project: Project) {
pendingKtFileChanges.processPending { file ->
if (file.virtualFile != null && file.virtualFile !in projectScope) {
LOG.debugIfEnabled(project, "Skip $file without vFile, or not in scope: ${file.virtualFile?.let { it !in projectScope }}")
LOG.debugIfEnabled(project) { "Skip $file without vFile, or not in scope: ${file.virtualFile?.let { it !in projectScope }}" }
return@processPending
}
val nullableModuleInfo = file.getNullableModuleInfo()
(nullableModuleInfo as? ModuleSourceInfo)?.let { invalidateCacheForModuleSourceInfo(it) }
if (nullableModuleInfo == null || nullableModuleInfo !is ModuleSourceInfo) {
LOG.debugIfEnabled(project, "Skip $file as it has mismatched ModuleInfo=$nullableModuleInfo")
LOG.debugIfEnabled(project) { "Skip $file as it has mismatched ModuleInfo=$nullableModuleInfo" }
}
implicitPackagePrefixCache.update(file)
}
@@ -329,7 +331,7 @@ class PerModulePackageCacheService(private val project: Project) {
return cacheForCurrentModuleInfo.getOrPut(packageFqName) {
val packageExists = PackageIndexUtil.packageExists(packageFqName, moduleInfo.contentScope(), project)
LOG.debugIfEnabled(project, "Computed cache value for $packageFqName in $moduleInfo is $packageExists")
LOG.debugIfEnabled(project) { "Computed cache value for $packageFqName in $moduleInfo is $packageExists" }
packageExists
}
}
@@ -351,16 +353,14 @@ class PerModulePackageCacheService(private val project: Project) {
}
}
private fun Logger.debugIfEnabled(project: Project, message: String, withCurrentTrace: Boolean = false) {
private fun Logger.debugIfEnabled(project: Project, withCurrentTrace: Boolean = false, message: () -> String) {
if (ApplicationManager.getApplication().isUnitTestMode && project.DEBUG_LOG_ENABLE_PerModulePackageCache) {
val msg = message()
if (withCurrentTrace) {
val e = Exception().apply { fillInStackTrace() }
this.debug(message, e)
this.debug(msg, e)
} else {
this.debug(message)
this.debug(msg)
}
}
}

View File

@@ -51,8 +51,8 @@ import org.jetbrains.kotlin.idea.core.script.dependencies.ScriptAdditionalIdeaDe
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.platform.DefaultIdeTargetPlatformKindProvider
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.contains
import org.jetbrains.kotlin.resolve.BindingContext
@@ -109,8 +109,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
syntheticFiles: Collection<KtFile> = listOf()
): ProjectResolutionFacade {
val sdk = dependenciesModuleInfo.sdk
val platform = /* Fallback to Common platform in CIDR (Java is not supported there) */
DefaultIdeTargetPlatformKindProvider.defaultPlatform // TODO: Js scripts?
val platform = JvmPlatforms.defaultJvmPlatform // TODO: Js scripts?
val settings = PlatformAnalysisSettings(
platform, sdk, true,
LanguageFeature.ReleaseCoroutines.defaultState == LanguageFeature.State.ENABLED

View File

@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.isRunningInCidrIde
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import kotlin.script.experimental.dependencies.ScriptReport
import kotlin.script.experimental.api.ScriptDiagnostic
object KotlinHighlightingUtil {
fun shouldHighlight(psiElement: PsiElement): Boolean {
@@ -71,7 +71,7 @@ object KotlinHighlightingUtil {
private fun shouldHighlightScript(ktFile: KtFile): Boolean {
if (isRunningInCidrIde) return false // There is no Java support in CIDR. So do not highlight errors in KTS if running in CIDR.
if (!ScriptsCompilationConfigurationUpdater.areDependenciesCached(ktFile)) return false
if (IdeScriptReportSink.getReports(ktFile.virtualFile).any { it.severity == ScriptReport.Severity.FATAL }) {
if (IdeScriptReportSink.getReports(ktFile.virtualFile).any { it.severity == ScriptDiagnostic.Severity.FATAL }) {
return false
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
// TODO: move to scripting-idea module
package org.jetbrains.kotlin.idea.script
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.extensions.ExtensionPointName
import kotlin.script.experimental.api.ScriptDiagnostic
interface ScriptDiagnosticFixProvider {
fun provideFixes(annotation: ScriptDiagnostic): List<IntentionAction>
companion object {
val EP_NAME = ExtensionPointName.create<ScriptDiagnosticFixProvider>("org.jetbrains.kotlin.scriptDiagnosticFixProvider")
}
}

View File

@@ -37,6 +37,7 @@ import com.intellij.openapi.wm.ex.StatusBarEx
import com.intellij.psi.PsiFile
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
import org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider
import org.jetbrains.kotlin.psi.KtFile
import kotlin.script.experimental.api.ScriptDiagnostic
import kotlin.script.experimental.api.SourceCode
@@ -54,19 +55,25 @@ class ScriptExternalHighlightingPass(
val reports = IdeScriptReportSink.getReports(file.virtualFile)
val annotations = reports.mapNotNull { (message, severity, _ , location) ->
val (startOffset, endOffset) = location?.let { computeOffsets(document, it) } ?: 0 to 0
val annotations = reports.mapNotNull { scriptDiagnostic ->
val (startOffset, endOffset) = scriptDiagnostic.location?.let { computeOffsets(document, it) } ?: 0 to 0
val annotation = Annotation(
startOffset,
endOffset,
severity.convertSeverity() ?: return@mapNotNull null,
message,
message
scriptDiagnostic.severity.convertSeverity() ?: return@mapNotNull null,
scriptDiagnostic.message,
scriptDiagnostic.message
)
// if range is empty, show notification panel in editor
annotation.isFileLevelAnnotation = startOffset == endOffset
for (provider in ScriptDiagnosticFixProvider.EP_NAME.extensions) {
provider.provideFixes(scriptDiagnostic).forEach {
annotation.registerFix(it)
}
}
annotation
}

View File

@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
import org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider
import org.jetbrains.kotlin.psi.KtFile
import kotlin.script.experimental.api.ScriptDiagnostic
import kotlin.script.experimental.api.SourceCode
@@ -75,19 +76,25 @@ class ScriptExternalHighlightingPass(
val reports = IdeScriptReportSink.getReports(file.virtualFile)
val annotations = reports.mapNotNull { (message, severity, _ , location) ->
val (startOffset, endOffset) = location?.let { computeOffsets(document, it) } ?: 0 to 0
val annotations = reports.mapNotNull { scriptDiagnostic ->
val (startOffset, endOffset) = scriptDiagnostic.location?.let { computeOffsets(document, it) } ?: 0 to 0
val annotation = Annotation(
startOffset,
endOffset,
severity.convertSeverity() ?: return@mapNotNull null,
message,
message
scriptDiagnostic.severity.convertSeverity() ?: return@mapNotNull null,
scriptDiagnostic.message,
scriptDiagnostic.message
)
// if range is empty, show notification panel in editor
annotation.isFileLevelAnnotation = startOffset == endOffset
for (provider in ScriptDiagnosticFixProvider.EP_NAME.extensions) {
provider.provideFixes(scriptDiagnostic).forEach {
annotation.registerFix(it)
}
}
annotation
}

View File

@@ -0,0 +1,5 @@
package org.jetbrains.annotations
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FIELD)
public annotation class PropertyKey(public val resourceBundle: String)

View File

@@ -0,0 +1,3 @@
foobar = 0
foo.bar = 1
bar.baz = 2

View File

@@ -0,0 +1,10 @@
import org.jetbrains.annotations.PropertyKey
fun message(@PropertyKey(resourceBundle = "MessageBundle1.dependency") key: String) = key
fun test() {
message("<caret>")
}
// ELEMENT: foo.bar
// CHARS: 'foo\n'

View File

@@ -0,0 +1,10 @@
import org.jetbrains.annotations.PropertyKey
fun message(@PropertyKey(resourceBundle = "MessageBundle1.dependency") key: String) = key
fun test() {
message("foo.bar")
}
// ELEMENT: foo.bar
// CHARS: 'foo\n'

View File

@@ -24,6 +24,7 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:"
private val TAIL_TEXT_PREFIX = "TAIL_TEXT:"
private val COMPLETION_CHAR_PREFIX = "CHAR:"
private val COMPLETION_CHARS_PREFIX = "CHARS:"
private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:"
protected open fun doTest(testPath: String) {
@@ -42,12 +43,10 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX)
val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX)
val completionCharString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX)
val completionChar = when(completionCharString) {
"\\n", null -> '\n'
"\\t" -> '\t'
else -> completionCharString.singleOrNull() ?: error("Incorrect completion char: \"$completionCharString\"")
}
val completionChars = completionChars(
char = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX),
chars = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHARS_PREFIX)
)
val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType
@@ -70,7 +69,15 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
}
}
doTestWithTextLoaded(completionType, invocationCount, lookupString, itemText, tailText, completionChar, File(testPath).name + ".after")
doTestWithTextLoaded(
completionType,
invocationCount,
lookupString,
itemText,
tailText,
completionChars,
File(testPath).name + ".after"
)
} finally {
if (configured) {
rollbackCompilerOptions(project, module)

View File

@@ -31,7 +31,7 @@ class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
private fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) {
fixture.configureByFile(fileName())
doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar, fileName() + ".after")
doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar.toString(), fileName() + ".after")
}
fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n')

View File

@@ -26,7 +26,7 @@ public class CompletionCharFilterTestGenerated extends AbstractCompletionCharFil
}
public void testAllFilesPresentInCharFilter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Colon.kt")
@@ -144,6 +144,11 @@ public class CompletionCharFilterTestGenerated extends AbstractCompletionCharFil
runTest("idea/idea-completion/testData/handlers/charFilter/LParenth.kt");
}
@TestMetadata("MessageBundle1.kt")
public void testMessageBundle1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/MessageBundle1.kt");
}
@TestMetadata("NamedParameter1.kt")
public void testNamedParameter1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/NamedParameter1.kt");

View File

@@ -20,26 +20,40 @@ abstract class CompletionHandlerTestBase() : KotlinLightCodeInsightFixtureTestCa
get() = myFixture
protected fun doTestWithTextLoaded(
completionType: CompletionType,
time: Int,
lookupString: String?,
itemText: String?,
tailText: String?,
completionChar: Char,
afterFilePath: String
completionType: CompletionType,
time: Int,
lookupString: String?,
itemText: String?,
tailText: String?,
completionChars: String,
afterFilePath: String
) {
for (idx in 0 until completionChars.length - 1) {
fixture.type(completionChars[idx])
}
fixture.complete(completionType, time)
if (lookupString != null || itemText != null || tailText != null) {
val item = getExistentLookupElement(lookupString, itemText, tailText)
if (item != null) {
selectItem(item, completionChar)
selectItem(item, completionChars.last())
}
}
fixture.checkResultByFile(afterFilePath)
}
protected fun completionChars(char: String?, chars: String?): String =
when (char) {
null -> when (chars) {
null -> "\n"
else -> chars.replace("\\n", "\n").replace("\\t", "\t")
}
"\\n" -> "\n"
"\\t" -> "\t"
else -> char.single().toString() ?: error("Incorrect completion char: \"$char\"")
}
protected fun getExistentLookupElement(lookupString: String?, itemText: String?, tailText: String?): LookupElement? {
val lookup = LookupManager.getInstance(project)?.activeLookup as LookupImpl? ?: return null
val items = lookup.items

View File

@@ -14,7 +14,7 @@ fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraName
val fileName = File(path).name
val noExtensionPath = FileUtil.getNameWithoutExtension(fileName)
val extensions = arrayOf("kt", "java")
val extensions = arrayOf("kt", "java", "properties")
val extraPaths: List<String> = extraNameParts
.flatMap { extensions.map { ext -> "$noExtensionPath$it.$ext" } }
.mapNotNull { File(testDataPath, it).takeIf { it.exists() }?.name }

View File

@@ -13,10 +13,12 @@ import com.intellij.openapi.module.ModuleUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ModulePackageIndex
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.Query
import com.intellij.util.io.parentSystemIndependentPath
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes
import org.jetbrains.jps.model.java.JavaSourceRootProperties
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
@@ -31,6 +33,8 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.addIfNotNull
import java.io.File
import java.net.URI
import java.nio.file.Paths
fun PsiDirectory.getPackage(): PsiPackage? = JavaDirectoryService.getInstance()!!.getPackage(this)
@@ -110,13 +114,21 @@ private fun Module.getOrConfigureKotlinSourceRoots(): List<VirtualFile> {
return sourceRoots
}
return runWriteAction {
val rootDir = rootManager.contentRoots.firstOrNull()
rootDir?.createChildDirectory(project, "kotlin")
getOrCreateRootDirectory()?.createChildDirectory(project, "kotlin")
project.invalidateProjectRoots()
getNonGeneratedKotlinSourceRoots()
}
}
private fun Module.getOrCreateRootDirectory(): VirtualFile? {
val contentEntry = rootManager.contentEntries.firstOrNull() ?: return null
contentEntry.file?.let { return it }
val path = Paths.get(URI.create(contentEntry.url))
val rootParent = LocalFileSystem.getInstance().findFileByPath(path.parentSystemIndependentPath)
return rootParent?.createChildDirectory(project, name.takeLastWhile { it != '.' })
}
private fun getPackageDirectoriesInModule(rootPackage: PsiPackage, module: Module): Array<PsiDirectory> =
rootPackage.getDirectories(GlobalSearchScope.moduleScope(module))

View File

@@ -147,7 +147,10 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
}
fun isReady(): Boolean {
return definitionsBySource.keys.all { source ->
if (definitions == null) {
reloadScriptDefinitions()
}
return definitions != null && definitionsBySource.keys.all { source ->
// TODO: implement another API for readiness checking
(source as? ScriptDefinitionContributor)?.isReady() != false
}

View File

@@ -30,6 +30,7 @@ import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependenciesLoader
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import java.io.File
@@ -125,7 +126,8 @@ class ScriptDependenciesManager internal constructor(
@TestOnly
fun updateScriptDependenciesSynchronously(virtualFile: VirtualFile, project: Project) {
val loader = SyncScriptDependenciesLoader(project)
loader.loadDependencies(virtualFile)
val scriptDefinition = virtualFile.findScriptDefinition(project) ?: return
loader.loadDependencies(virtualFile, scriptDefinition)
loader.notifyRootsChanged()
}
}

View File

@@ -32,7 +32,6 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiManager
import com.intellij.util.Alarm
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.core.script.dependencies.AsyncScriptDependenciesLoader
import org.jetbrains.kotlin.idea.core.script.dependencies.FromFileAttributeScriptDependenciesLoader
import org.jetbrains.kotlin.idea.core.script.dependencies.OutsiderFileDependenciesLoader
@@ -43,6 +42,7 @@ import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.isNonScript
import org.jetbrains.kotlin.scripting.resolve.LegacyResolverWrapper
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
@@ -101,7 +101,8 @@ class ScriptsCompilationConfigurationUpdater(
if (!ScriptDefinitionsManager.getInstance(project).isReady()) return
if (!cache.shouldRunDependenciesUpdate(file)) return
loaders.filter { it.isApplicable(file) }.forEach { it.loadDependencies(file) }
val scriptDefinition = file.findScriptDefinition(project) ?: return
loaders.filter { it.isApplicable(file, scriptDefinition) }.forEach { it.loadDependencies(file, scriptDefinition) }
}
private fun makeRootsChangeIfNeeded() {
@@ -161,7 +162,7 @@ class ScriptsCompilationConfigurationUpdater(
}
private fun shouldStartUpdate(file: VirtualFile): Boolean {
if (project.isDisposed || !file.isValid || file.fileType != KotlinFileType.INSTANCE) {
if (project.isDisposed || !file.isValid || file.isNonScript()) {
return false
}

View File

@@ -14,6 +14,7 @@ import com.intellij.openapi.vfs.VirtualFile
import kotlinx.coroutines.Runnable
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
@@ -28,12 +29,17 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr
private var notifyRootChange: Boolean = false
private var backgroundTasksQueue: LoaderBackgroundTask? = null
override fun isApplicable(file: VirtualFile): Boolean {
val scriptDefinition = file.findScriptDefinition(project) ?: return false
override fun isApplicable(
file: VirtualFile,
scriptDefinition: ScriptDefinition
): Boolean {
return ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
}
override fun loadDependencies(file: VirtualFile) {
override fun loadDependencies(
file: VirtualFile,
scriptDefinition: ScriptDefinition
) {
lock.write {
if (backgroundTasksQueue == null) {
backgroundTasksQueue = LoaderBackgroundTask()

View File

@@ -9,7 +9,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.core.script.scriptCompilationConfiguration
import org.jetbrains.kotlin.idea.core.script.scriptDependencies
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import kotlin.script.experimental.api.asSuccess
@@ -17,22 +17,31 @@ import kotlin.script.experimental.api.asSuccess
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
override fun isApplicable(file: VirtualFile): Boolean {
override fun isApplicable(
file: VirtualFile,
scriptDefinition: ScriptDefinition
): Boolean {
return file.scriptDependencies != null || file.scriptCompilationConfiguration != null
}
override fun loadDependencies(file: VirtualFile) {
override fun loadDependencies(
file: VirtualFile,
scriptDefinition: ScriptDefinition
) {
file.scriptCompilationConfiguration?.let {
ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(VirtualFileScriptSource(file), it).apply {
debug(file) { "refined configuration from fileAttributes = $it" }
}
} ?: file.scriptDependencies?.let {
ScriptCompilationConfigurationWrapper.FromLegacy(VirtualFileScriptSource(file), it, file.findScriptDefinition(project)).apply {
ScriptCompilationConfigurationWrapper.FromLegacy(VirtualFileScriptSource(file), it, scriptDefinition).apply {
debug(file) { "dependencies from fileAttributes = $it" }
}
}?.let {
if (areDependenciesValid(file, it)) {
saveToCache(file, it.asSuccess(), skipSaveToAttributes = true)
} else {
file.scriptCompilationConfiguration = null
file.scriptDependencies = null
}
}
}

View File

@@ -10,13 +10,20 @@ import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
import org.jetbrains.kotlin.idea.highlighter.OutsidersPsiFileSupportUtils
import org.jetbrains.kotlin.idea.highlighter.OutsidersPsiFileSupportWrapper
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
class OutsiderFileDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
override fun isApplicable(file: VirtualFile): Boolean {
override fun isApplicable(
file: VirtualFile,
scriptDefinition: ScriptDefinition
): Boolean {
return OutsidersPsiFileSupportWrapper.isOutsiderFile(file)
}
override fun loadDependencies(file: VirtualFile) {
override fun loadDependencies(
file: VirtualFile,
scriptDefinition: ScriptDefinition
) {
val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, file) ?: return
val compilationConfiguration = ScriptDependenciesManager.getInstance(project).getRefinedCompilationConfiguration(fileOrigin) ?: return
saveToCache(file, compilationConfiguration)

View File

@@ -15,6 +15,7 @@ import com.intellij.openapi.util.EmptyRunnable
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.core.script.*
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
@@ -24,8 +25,8 @@ import kotlin.script.experimental.api.valueOrNull
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
abstract class ScriptDependenciesLoader(protected val project: Project) {
abstract fun isApplicable(file: VirtualFile): Boolean
abstract fun loadDependencies(file: VirtualFile)
abstract fun isApplicable(file: VirtualFile, scriptDefinition: ScriptDefinition): Boolean
abstract fun loadDependencies(file: VirtualFile, scriptDefinition: ScriptDefinition)
protected abstract fun shouldShowNotification(): Boolean

View File

@@ -8,20 +8,24 @@ package org.jetbrains.kotlin.idea.core.script.dependencies
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
class SyncScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
override fun isApplicable(file: VirtualFile): Boolean {
val scriptDefinition = file.findScriptDefinition(project) ?: return false
override fun isApplicable(
file: VirtualFile,
scriptDefinition: ScriptDefinition
): Boolean {
return !ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
}
override fun loadDependencies(file: VirtualFile) {
val scriptDef = file.findScriptDefinition(project) ?: return
override fun loadDependencies(
file: VirtualFile,
scriptDefinition: ScriptDefinition
) {
debug(file) { "start sync dependencies loading" }
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDef, project)
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDefinition, project)
debug(file) { "finish sync dependencies loading" }
processRefinedConfiguration(result, file)
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.actions
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.ide.actions.ShowFilePathAction
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.wm.WindowManager
import com.intellij.psi.PsiFile
import com.intellij.ui.BrowserHyperlinkListener
import java.io.File
class ShowKotlinGradleDslLogs : IntentionAction, AnAction(), DumbAware {
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
openLogsDirIfPresent(project)
}
override fun actionPerformed(e: AnActionEvent) {
openLogsDirIfPresent(e.project)
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?) = ShowFilePathAction.isSupported()
override fun update(e: AnActionEvent) {
val presentation = e.presentation
presentation.isVisible = ShowFilePathAction.isSupported()
presentation.text = NAME
}
private fun openLogsDirIfPresent(project: Project?) {
val logsDir = findLogsDir()
if (logsDir != null) {
ShowFilePathAction.openDirectory(logsDir)
} else {
val parent = WindowManager.getInstance().getStatusBar(project)?.component
?: WindowManager.getInstance().findVisibleFrame().rootPane
JBPopupFactory.getInstance()
.createHtmlTextBalloonBuilder(
"Gradle DSL Logs cannot be found automatically.<br/>See how to find logs <a href=\"$gradleTroubleshootingLink\">here</a>.",
MessageType.ERROR,
BrowserHyperlinkListener.INSTANCE
)
.setFadeoutTime(5000)
.createBalloon()
.showInCenterOf(parent)
}
}
/** The way how to find Gradle logs is described here
* @see org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs.gradleTroubleshootingLink
*/
private fun findLogsDir(): File? {
val userHome = System.getProperty("user.home")
return when {
SystemInfo.isMac -> File("$userHome/Library/Logs/gradle-kotlin-dsl")
SystemInfo.isLinux -> File("$userHome/.gradle-kotlin-dsl/logs")
SystemInfo.isWindows -> File("$userHome/AppData/Local/gradle-kotlin-dsl/log")
else -> null
}.takeIf { it?.exists() == true }
}
override fun startInWriteAction() = false
override fun getText() = NAME
override fun getFamilyName() = NAME
companion object {
private const val gradleTroubleshootingLink = "https://docs.gradle.org/current/userguide/kotlin_dsl.html#troubleshooting"
val NAME = "Show Kotlin Gradle DSL Logs in ${ShowFilePathAction.getFileManagerName()}"
}
}

View File

@@ -92,6 +92,16 @@ fun GradleBuildScriptManipulator<*>.useNewSyntax(kotlinPluginName: String, gradl
return !hasOldApply
}
fun GradleBuildScriptManipulator<*>.usesNewMultiplatform(): Boolean {
val fileText = runReadAction { scriptFile.text }
return fileText.contains("multiplatform")
}
fun LanguageFeature.State.assertApplicableInMultiplatform() {
if (this == LanguageFeature.State.ENABLED_WITH_ERROR || this == LanguageFeature.State.DISABLED)
throw UnsupportedOperationException("Disabling the language feature is unsupported for multiplatform")
}
private val MIN_GRADLE_VERSION_FOR_API_AND_IMPLEMENTATION = GradleVersion.version("3.4")
fun GradleVersion.scope(directive: String): String {

View File

@@ -35,7 +35,7 @@ import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder
import org.jetbrains.plugins.gradle.frameworkSupport.GradleFrameworkSupportProvider
import javax.swing.Icon
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JTextPane
abstract class GradleKotlinFrameworkSupportProvider(
val frameworkTypeId: String,
@@ -57,7 +57,11 @@ abstract class GradleKotlinFrameworkSupportProvider(
configurable.addSupport(module, rootModel, modifiableModelsProvider)
}
override fun createComponent(): JComponent = JLabel(getDescription())
override fun createComponent(): JComponent {
val jTextPane = JTextPane()
jTextPane.text = getDescription()
return jTextPane
}
}
}
@@ -184,7 +188,7 @@ open class GradleKotlinJavaFrameworkSupportProvider(
}
}
override fun getDescription() = "A Kotlin library or application targeting the JVM"
override fun getDescription() = "A single-platform Kotlin library or application targeting the JVM"
}
abstract class GradleKotlinJSFrameworkSupportProvider(
@@ -209,7 +213,7 @@ abstract class GradleKotlinJSFrameworkSupportProvider(
override fun getPluginExpression() = "id 'org.jetbrains.kotlin.js'"
override fun getDependencies(sdk: Sdk?) = listOf(MAVEN_JS_STDLIB_ID)
override fun getTestDependencies() = listOf(MAVEN_JS_TEST_ID)
override fun getDescription() = "A Kotlin library or application targeting JavaScript"
override fun getDescription() = "A single-platform Kotlin library or application targeting JavaScript"
}
open class GradleKotlinJSBrowserFrameworkSupportProvider(
@@ -219,7 +223,7 @@ open class GradleKotlinJSBrowserFrameworkSupportProvider(
override val jsSubTargetName: String
get() = "browser"
override fun getDescription() = "A Kotlin library or application targeting JavaScript for browser"
override fun getDescription() = "A single-platform Kotlin library or application targeting JavaScript for browser"
}
open class GradleKotlinJSNodeFrameworkSupportProvider(
@@ -229,11 +233,11 @@ open class GradleKotlinJSNodeFrameworkSupportProvider(
override val jsSubTargetName: String
get() = "nodejs"
override fun getDescription() = "A Kotlin library or application targeting JavaScript for Node.js"
override fun getDescription() = "A single-platform Kotlin library or application targeting JavaScript for Node.js"
}
class GradleKotlinMPPFrameworkSupportProvider : GradleKotlinFrameworkSupportProvider(
"KOTLIN_MPP", "Kotlin (Multiplatform - Experimental)", KotlinIcons.MPP
open class GradleKotlinMPPFrameworkSupportProvider : GradleKotlinFrameworkSupportProvider(
"KOTLIN_MPP", "Kotlin/Multiplatform", KotlinIcons.MPP
) {
override fun getPluginId() = "org.jetbrains.kotlin.multiplatform"
override fun getPluginExpression() = "id 'org.jetbrains.kotlin.multiplatform'"
@@ -241,6 +245,43 @@ class GradleKotlinMPPFrameworkSupportProvider : GradleKotlinFrameworkSupportProv
override fun getDependencies(sdk: Sdk?): List<String> = listOf()
override fun getTestDependencies(): List<String> = listOf()
override fun getDescription() = "Kotlin multiplatform code"
override fun getDescription() =
"Multi-targeted (JVM, JS, iOS, etc.) project with shared code in common modules. " +
"The targets can be configured in the project's build script."
}
open class GradleKotlinMPPSourceSetsFrameworkSupportProvider : GradleKotlinMPPFrameworkSupportProvider() {
override fun addSupport(
buildScriptData: BuildScriptDataBuilder,
module: Module,
sdk: Sdk?,
specifyPluginVersionIfNeeded: Boolean,
explicitPluginVersion: String?
) {
super.addSupport(buildScriptData, module, sdk, specifyPluginVersionIfNeeded, explicitPluginVersion)
buildScriptData.addOther(
"""kotlin {
/* Targets configuration omitted.
* To find out how to configure the targets, please follow the link:
* https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets */
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
}
}"""
)
}
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration
@@ -165,6 +154,15 @@ class GroovyBuildScriptManipulator(
state: LanguageFeature.State,
forTests: Boolean
): PsiElement? {
if (usesNewMultiplatform()) {
state.assertApplicableInMultiplatform()
val kotlinBlock = scriptFile.getBlockOrCreate("kotlin")
val sourceSetsBlock = kotlinBlock.getBlockOrCreate("sourceSets")
val allBlock = sourceSetsBlock.getBlockOrCreate("all")
allBlock.addLastExpressionInBlockIfNeeded("languageSettings.enableLanguageFeature(\"${feature.name}\")")
return allBlock.statements.lastOrNull()
}
val featureArgumentString = feature.buildArgumentString(state)
val parameterName = "freeCompilerArgs"
return addOrReplaceKotlinTaskParameter(
@@ -253,11 +251,6 @@ class GroovyBuildScriptManipulator(
)
}
private fun usesNewMultiplatform(): Boolean {
val fileText = runReadAction { scriptFile.text }
return fileText.contains("kotlin-multiplatform")
}
private fun GrClosableBlock.addParameterAssignment(
parameterName: String,
defaultValue: String,

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration
@@ -146,13 +135,13 @@ class KotlinBuildScriptManipulator(
private fun KtBlockExpression.addCompileStdlibIfMissing(stdlibArtifactName: String): KtCallExpression? =
findStdLibDependency()
?: addExpressionIfMissing(
getCompileDependencySnippet(
KOTLIN_GROUP_ID,
stdlibArtifactName,
version = "\$$GSK_KOTLIN_VERSION_PROPERTY_NAME"
)
) as? KtCallExpression
?: addExpressionIfMissing(
getCompileDependencySnippet(
KOTLIN_GROUP_ID,
stdlibArtifactName,
version = "\$$GSK_KOTLIN_VERSION_PROPERTY_NAME"
)
) as? KtCallExpression
private fun addPluginRepositoryExpression(expression: String) {
scriptFile.getPluginManagementBlock()?.findOrCreateBlock("repositories")?.addExpressionIfMissing(expression)
@@ -172,7 +161,7 @@ class KotlinBuildScriptManipulator(
?.findOrCreateBlock("resolutionStrategy")
?.findOrCreateBlock("eachPlugin")
?.addExpressionIfMissing(
"""
"""
if (requested.id.id == "$pluginId") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${'$'}{requested.version}")
}
@@ -181,7 +170,12 @@ class KotlinBuildScriptManipulator(
}
private fun KtBlockExpression.addNoVersionCompileStdlibIfMissing(stdlibArtifactName: String): KtCallExpression? =
findStdLibDependency() ?: addExpressionIfMissing("implementation(${getKotlinModuleDependencySnippet(stdlibArtifactName, null)})") as? KtCallExpression
findStdLibDependency() ?: addExpressionIfMissing(
"implementation(${getKotlinModuleDependencySnippet(
stdlibArtifactName,
null
)})"
) as? KtCallExpression
private fun KtFile.containsCompileStdLib(): Boolean =
findScriptInitializer("dependencies")?.getBlock()?.findStdLibDependency() != null
@@ -200,10 +194,10 @@ class KotlinBuildScriptManipulator(
private fun KtBlockExpression.findPluginInPluginsGroup(pluginName: String): KtCallExpression? {
return PsiTreeUtil.getChildrenOfAnyType(
this,
KtCallExpression::class.java,
KtBinaryExpression::class.java,
KtDotQualifiedExpression::class.java
this,
KtCallExpression::class.java,
KtBinaryExpression::class.java,
KtDotQualifiedExpression::class.java
).mapNotNull {
when (it) {
is KtCallExpression -> it
@@ -233,15 +227,14 @@ class KotlinBuildScriptManipulator(
}
private fun KtScriptInitializer.getBlock(): KtBlockExpression? =
PsiTreeUtil.findChildOfType<KtCallExpression>(this, KtCallExpression::class.java)?.getBlock()
PsiTreeUtil.findChildOfType(this, KtCallExpression::class.java)?.getBlock()
private fun KtCallExpression.getBlock(): KtBlockExpression? =
(valueArguments.singleOrNull()?.getArgumentExpression() as? KtLambdaExpression)?.bodyExpression
private fun KtFile.getKotlinStdlibVersion(): String? {
return findScriptInitializer("dependencies")?.getBlock()?.let {
val expression = it.findStdLibDependency()?.valueArguments?.firstOrNull()?.getArgumentExpression()
when (expression) {
when (val expression = it.findStdLibDependency()?.valueArguments?.firstOrNull()?.getArgumentExpression()) {
is KtCallExpression -> expression.valueArguments.getOrNull(1)?.text?.trim('\"')
is KtStringTemplateExpression -> expression.text?.trim('\"')?.substringAfterLast(":")?.removePrefix("$")
else -> null
@@ -253,7 +246,7 @@ class KotlinBuildScriptManipulator(
return PsiTreeUtil.getChildrenOfType(this, KtCallExpression::class.java)?.find {
val calleeText = it.calleeExpression?.text
calleeText in PRODUCTION_DEPENDENCY_STATEMENTS && (it.valueArguments.firstOrNull()?.getArgumentExpression()?.isKotlinStdLib()
?: false)
?: false)
}
}
@@ -267,22 +260,18 @@ class KotlinBuildScriptManipulator(
else -> false
}
private fun KtFile.getPluginManagementBlock(): KtBlockExpression? =
findScriptInitializer("pluginManagement")?.getBlock() ?: addTopLevelBlock("pluginManagement", true)
private fun KtFile.getPluginManagementBlock(): KtBlockExpression? = findOrCreateScriptInitializer("pluginManagement", true)
private fun KtFile.getRepositoriesBlock(): KtBlockExpression? =
findScriptInitializer("repositories")?.getBlock() ?: addTopLevelBlock("repositories")
private fun KtFile.getRepositoriesBlock(): KtBlockExpression? = findOrCreateScriptInitializer("repositories")
private fun KtFile.getDependenciesBlock(): KtBlockExpression? =
findScriptInitializer("dependencies")?.getBlock() ?: addTopLevelBlock("dependencies")
private fun KtFile.getDependenciesBlock(): KtBlockExpression? = findOrCreateScriptInitializer("dependencies")
private fun KtFile.getPluginsBlock(): KtBlockExpression? =
findScriptInitializer("plugins")?.getBlock() ?: addTopLevelBlock("plugins", true)
private fun KtFile.getPluginsBlock(): KtBlockExpression? = findOrCreateScriptInitializer("plugins", true)
private fun KtFile.createPluginInPluginsGroupIfMissing(pluginName: String, version: String): KtCallExpression? =
getPluginsBlock()?.let {
it.findPluginInPluginsGroup(pluginName)
?: it.addExpressionIfMissing("$pluginName version \"$version\"") as? KtCallExpression
?: it.addExpressionIfMissing("$pluginName version \"$version\"") as? KtCallExpression
}
private fun KtFile.createApplyBlock(): KtBlockExpression? {
@@ -300,7 +289,7 @@ class KotlinBuildScriptManipulator(
private fun KtFile.changeCoroutineConfiguration(coroutineOption: String): PsiElement? {
val snippet = "experimental.coroutines = Coroutines.${coroutineOption.toUpperCase()}"
val kotlinBlock = findScriptInitializer("kotlin")?.getBlock() ?: addTopLevelBlock("kotlin") ?: return null
val kotlinBlock = findOrCreateScriptInitializer("kotlin") ?: return null
addImportIfMissing("org.jetbrains.kotlin.gradle.dsl.Coroutines")
val statement = kotlinBlock.statements.find { it.text.startsWith("experimental.coroutines") }
return if (statement != null) {
@@ -315,6 +304,14 @@ class KotlinBuildScriptManipulator(
state: LanguageFeature.State,
forTests: Boolean
): PsiElement? {
if (usesNewMultiplatform()) {
state.assertApplicableInMultiplatform()
return findOrCreateScriptInitializer("kotlin")
?.findOrCreateBlock("sourceSets")
?.findOrCreateBlock("all")
?.addExpressionIfMissing("languageSettings.enableLanguageFeature(\"${feature.name}\")")
}
val featureArgumentString = feature.buildArgumentString(state)
val parameterName = "freeCompilerArgs"
return addOrReplaceKotlinTaskParameter(
@@ -363,14 +360,14 @@ class KotlinBuildScriptManipulator(
}
}
private fun KtFile.getBuildScriptBlock(): KtBlockExpression? =
findScriptInitializer("buildscript")?.getBlock() ?: addTopLevelBlock("buildscript", true)
private fun KtFile.getBuildScriptBlock(): KtBlockExpression? = findOrCreateScriptInitializer("buildscript", true)
private fun KtBlockExpression.getRepositoriesBlock(): KtBlockExpression? =
findBlock("repositories") ?: addBlock("repositories")
private fun KtFile.findOrCreateScriptInitializer(name: String, first: Boolean = false): KtBlockExpression? =
findScriptInitializer(name)?.getBlock() ?: addTopLevelBlock(name, first)
private fun KtBlockExpression.getDependenciesBlock(): KtBlockExpression? =
findBlock("dependencies") ?: addBlock("dependencies")
private fun KtBlockExpression.getRepositoriesBlock(): KtBlockExpression? = findOrCreateBlock("repositories")
private fun KtBlockExpression.getDependenciesBlock(): KtBlockExpression? = findOrCreateBlock("dependencies")
private fun KtBlockExpression.addRepositoryIfMissing(version: String): KtCallExpression? {
val snippet = getRepositorySnippet(version) ?: return null
@@ -425,17 +422,15 @@ class KotlinBuildScriptManipulator(
private fun KtFile.addImportIfMissing(path: String): KtImportDirective =
importDirectives.find { it.importPath?.pathStr == path } ?: importList?.add(
psiFactory.createImportDirective(
ImportPath.fromString(
path
)
psiFactory.createImportDirective(
ImportPath.fromString(
path
)
)
) as KtImportDirective
private fun KtBlockExpression.addExpressionAfterIfMissing(text: String, after: PsiElement): KtExpression = addStatementIfMissing(text) {
psiFactory.createExpression(it).let { created ->
addAfter(created, after)
}
addAfter(psiFactory.createExpression(it), after)
}
private fun KtBlockExpression.addExpressionIfMissing(text: String, first: Boolean = false): KtExpression = addStatementIfMissing(text) {
@@ -494,8 +489,8 @@ class KotlinBuildScriptManipulator(
}
companion object {
private val STDLIB_ARTIFACT_PREFIX = "org.jetbrains.kotlin:kotlin-stdlib"
val GSK_KOTLIN_VERSION_PROPERTY_NAME = "kotlin_version"
private const val STDLIB_ARTIFACT_PREFIX = "org.jetbrains.kotlin:kotlin-stdlib"
const val GSK_KOTLIN_VERSION_PROPERTY_NAME = "kotlin_version"
fun getKotlinGradlePluginClassPathSnippet(): String =
"classpath(${getKotlinModuleDependencySnippet("gradle-plugin", "\$$GSK_KOTLIN_VERSION_PROPERTY_NAME")})"

View File

@@ -80,7 +80,6 @@ abstract class KotlinDslGradleKotlinFrameworkSupportProvider(
buildScriptData
.addPluginDefinitionInPluginsGroup(getPluginDefinition() + " version \"$kotlinVersion\"")
.addDependencyNotation(getRuntimeLibrary(rootModel, null))
} else {
if (additionalRepository != null) {
val repository = additionalRepository.toKotlinRepositorySnippet()
@@ -95,7 +94,6 @@ abstract class KotlinDslGradleKotlinFrameworkSupportProvider(
.addBuildscriptRepositoriesDefinition("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\"")
.addDependencyNotation(getRuntimeLibrary(rootModel, "\$$GSK_KOTLIN_VERSION_PROPERTY_NAME"))
.addBuildscriptDependencyNotation(getKotlinGradlePluginClassPathSnippet())
}
@@ -112,10 +110,15 @@ abstract class KotlinDslGradleKotlinFrameworkSupportProvider(
private fun RepositoryDescription.toKotlinRepositorySnippet() = "maven { setUrl(\"$url\") }"
protected abstract fun getRuntimeLibrary(rootModel: ModifiableRootModel, version: String?): String
protected abstract fun getOldSyntaxPluginDefinition(): String
protected abstract fun getPluginDefinition(): String
protected fun composeDependency(buildScriptData: BuildScriptDataBuilder, artifactId: String): String {
return if (buildScriptData.gradleVersion >= MIN_GRADLE_VERSION_FOR_NEW_PLUGIN_SYNTAX)
"implementation(${getKotlinModuleDependencySnippet(artifactId, null)})"
else
"implementation(${getKotlinModuleDependencySnippet(artifactId, "\$$GSK_KOTLIN_VERSION_PROPERTY_NAME")})"
}
}
class KotlinDslGradleKotlinJavaFrameworkSupportProvider :
@@ -124,9 +127,6 @@ class KotlinDslGradleKotlinJavaFrameworkSupportProvider :
override fun getOldSyntaxPluginDefinition() = "plugin(\"${KotlinGradleModuleConfigurator.KOTLIN}\")"
override fun getPluginDefinition() = "kotlin(\"jvm\")"
override fun getRuntimeLibrary(rootModel: ModifiableRootModel, version: String?) =
"implementation(${getKotlinModuleDependencySnippet(getStdlibArtifactId(rootModel.sdk, bundledRuntimeVersion()), version)})"
override fun addSupport(
projectId: ProjectId,
module: Module,
@@ -141,6 +141,9 @@ class KotlinDslGradleKotlinJavaFrameworkSupportProvider :
.addImport("import org.jetbrains.kotlin.gradle.tasks.KotlinCompile")
.addOther("tasks.withType<KotlinCompile> {\n kotlinOptions.jvmTarget = \"1.8\"\n}\n")
}
val artifactId = getStdlibArtifactId(rootModel.sdk, bundledRuntimeVersion())
buildScriptData.addDependencyNotation(composeDependency(buildScriptData, artifactId))
}
}
@@ -160,13 +163,13 @@ abstract class AbstractKotlinDslGradleKotlinJSFrameworkSupportProvider(
super.addSupport(projectId, module, rootModel, modifiableModelsProvider, buildScriptData)
buildScriptData.addOther("kotlin.target.$jsSubTargetName { }")
val artifactId = MAVEN_JS_STDLIB_ID.removePrefix("kotlin-")
buildScriptData.addDependencyNotation(composeDependency(buildScriptData, artifactId))
}
override fun getOldSyntaxPluginDefinition(): String = "plugin(\"${KotlinJsGradleModuleConfigurator.KOTLIN_JS}\")"
override fun getPluginDefinition(): String = "id(\"org.jetbrains.kotlin.js\")"
override fun getRuntimeLibrary(rootModel: ModifiableRootModel, version: String?) =
"implementation(${getKotlinModuleDependencySnippet(MAVEN_JS_STDLIB_ID.removePrefix("kotlin-"), version)})"
}
class KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider :
@@ -180,3 +183,42 @@ class KotlinDslGradleKotlinJSNodeFrameworkSupportProvider :
override val jsSubTargetName: String
get() = "nodejs"
}
class KotlinDslGradleKotlinMPPFrameworkSupportProvider :
KotlinDslGradleKotlinFrameworkSupportProvider("KOTLIN_MPP", "Kotlin/Multiplatform", KotlinIcons.MPP) {
override fun getOldSyntaxPluginDefinition() = "plugin(\"org.jetbrains.kotlin.multiplatform\")"
override fun getPluginDefinition() = "kotlin(\"multiplatform\")"
override fun addSupport(
projectId: ProjectId,
module: Module,
rootModel: ModifiableRootModel,
modifiableModelsProvider: ModifiableModelsProvider,
buildScriptData: BuildScriptDataBuilder
) {
super.addSupport(projectId, module, rootModel, modifiableModelsProvider, buildScriptData)
buildScriptData.addOther(
"""kotlin {
/* Targets configuration omitted.
* To find out how to configure the targets, please follow the link:
* https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets */
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
}
}"""
)
}
}

View File

@@ -57,6 +57,8 @@ var DataNode<out ModuleData>.isHmpp
by NotNullableCopyableDataNodeUserDataProperty(Key.create<Boolean>("IS_HMPP_MODULE"), false)
var DataNode<ModuleData>.platformPluginId
by CopyableDataNodeUserDataProperty(Key.create<String>("PLATFORM_PLUGIN_ID"))
var DataNode<ModuleData>.kotlinNativeHome
by CopyableDataNodeUserDataProperty(Key.create<String>("KOTLIN_NATIVE_HOME"))
var DataNode<out ModuleData>.implementedModuleNames
by NotNullableCopyableDataNodeUserDataProperty(Key.create<List<String>>("IMPLEMENTED_MODULE_NAME"), emptyList())
// Project is usually the same during all import, thus keeping Map Project->Dependencies makes model a bit more complicated but allows to avoid future problems

View File

@@ -15,10 +15,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.util.Key
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.gradle.KotlinModule
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.gradle.KotlinPlatformContainer
import org.jetbrains.kotlin.gradle.KotlinPlatformContainerImpl
import org.jetbrains.kotlin.gradle.*
import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File
@@ -59,6 +56,7 @@ class KotlinAndroidSourceSetData(
class KotlinTargetData(name: String) : AbstractNamedData(GradleConstants.SYSTEM_ID, name) {
var moduleIds: Set<String> = emptySet()
var archiveFile: File? = null
var konanArtifacts: Collection<KonanArtifactModel>? = null
companion object {
val KEY = ExternalKey.create(KotlinTargetData::class.java, ProjectKeys.MODULE.processingWeight + 1)

View File

@@ -206,6 +206,8 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
val mppModel = resolverCtx.getMppModel(gradleModule)
if (mppModel == null || externalProject == null) return
mainModuleNode.kotlinNativeHome = mppModel.kotlinNativeHome
val jdkName = gradleModule.jdkNameIfAny
// save artefacts locations.
@@ -244,6 +246,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
if (target.name == KotlinTarget.METADATA_TARGET_NAME) continue
val targetData = KotlinTargetData(target.name).also {
it.archiveFile = target.jar?.archiveFile
it.konanArtifacts = target.konanArtifacts
}
val targetDataNode = mainModuleNode.createChild<KotlinTargetData>(KotlinTargetData.KEY, targetData)

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.script
import com.intellij.codeInsight.intention.IntentionAction
import org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs
import kotlin.script.experimental.api.ScriptDiagnostic
class GradleScriptDiagnosticFixProvider : ScriptDiagnosticFixProvider {
override fun provideFixes(annotation: ScriptDiagnostic): List<IntentionAction> {
if (gradleMessagesForQuickFix.any { annotation.message.contains(it) }) {
return listOf(ShowKotlinGradleDslLogs())
}
return emptyList()
}
private val gradleMessagesForQuickFix = arrayListOf(
"This script caused build configuration to fail",
"see IDE logs for more information",
"Script dependencies resolution failed"
)
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -31,7 +31,7 @@ class GradleConfiguratorPlatformSpecificTest : GradleImportingTestCase() {
@TargetVersions("4.7+")
@Test
fun testEnableFeatureSupportMultiplatformWithDots() {
fun testEnableFeatureSupportMultiplatform2() {
val files = importProjectFromTestData()
runInEdtAndWait {
@@ -61,6 +61,22 @@ class GradleConfiguratorPlatformSpecificTest : GradleImportingTestCase() {
}
}
@TargetVersions("4.7+")
@Test
fun testEnableFeatureSupportMultiplatformKts() {
val files = importProjectFromTestData()
runInEdtAndWait {
myTestFixture.project.executeWriteCommand("") {
KotlinWithGradleConfigurator.changeFeatureConfiguration(
myTestFixture.module, LanguageFeature.InlineClasses, LanguageFeature.State.ENABLED, false
)
}
checkFiles(files)
}
}
override fun testDataDirName(): String {
return "configurator"
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2000-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -584,22 +584,6 @@ class GradleConfiguratorTest : GradleImportingTestCase() {
}
}
@TargetVersions("4.7+")
@Test
fun testDisableFeatureSupportMultiplatform() {
val files = importProjectFromTestData()
runInEdtAndWait {
myTestFixture.project.executeWriteCommand("") {
KotlinWithGradleConfigurator.changeFeatureConfiguration(
myTestFixture.module, LanguageFeature.InlineClasses, LanguageFeature.State.DISABLED, false
)
}
checkFiles(files)
}
}
@Test
fun testEnableFeatureSupport() {
val files = importProjectFromTestData()

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.inspections
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.EditorNotificationPanel
import com.intellij.ui.EditorNotifications
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.framework.isGradleModule
import org.jetbrains.kotlin.idea.util.findModule
import org.jetbrains.kotlin.idea.util.sourceRoots
class JavaOutsideModuleDetector(private val project: Project) : EditorNotifications.Provider<EditorNotificationPanel>() {
override fun getKey(): Key<EditorNotificationPanel> = KEY
override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor): EditorNotificationPanel? {
if (file.fileType != JavaFileType.INSTANCE) return null
val module = file.findModule(project) ?: return null
if (!module.isGradleModule()) return null
val facetSettings = KotlinFacet.get(module)?.configuration?.settings ?: return null
val filePath = file.path
val nonKotlinPath = module.sourceRoots.map { it.path } - facetSettings.pureKotlinSourceFolders
if (nonKotlinPath.any { filePath.startsWith(it) }) return null
return EditorNotificationPanel().apply {
setText("This .java file is outside of Java source roots and won't be added to the class-path.")
}
}
companion object {
private val KEY = Key.create<EditorNotificationPanel>("JavaOutsideModuleDetector")
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

View File

@@ -38,10 +38,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
class NativePlatformKindResolution : IdePlatformKindResolution {
override fun createLibraryInfo(project: Project, library: Library): List<LibraryInfo> {
return library.getFiles(OrderRootType.CLASSES)
.mapNotNull { file -> PathUtil.getLocalPath(file) }
.map { path -> File(path) }
.map { file -> NativeLibraryInfo(project, library, file) }
return library.getFiles(OrderRootType.CLASSES).mapNotNull { file ->
if (!isLibraryFileForPlatform(file)) return@createLibraryInfo emptyList()
val path = PathUtil.getLocalPath(file) ?: return@createLibraryInfo emptyList()
NativeLibraryInfo(project, library, File(path))
}
}
override fun isLibraryFileForPlatform(virtualFile: VirtualFile): Boolean {

View File

@@ -119,7 +119,7 @@ enum class KotlinPlatform(val id: String) {
}
}
interface KotlinPlatformContainer: Serializable {
interface KotlinPlatformContainer : Serializable {
val platforms: Collection<KotlinPlatform>
fun supports(simplePlatform: KotlinPlatform): Boolean
@@ -142,6 +142,7 @@ interface KotlinTarget : Serializable {
val compilations: Collection<KotlinCompilation>
val testTasks: Collection<KotlinTestTask>
val jar: KotlinTargetJar?
val konanArtifacts: List<KonanArtifactModel>
companion object {
const val METADATA_TARGET_NAME = "metadata"
@@ -167,4 +168,29 @@ interface KotlinMPPGradleModel : Serializable {
companion object {
const val NO_KOTLIN_NATIVE_HOME = ""
}
}
}
interface KonanArtifactModel : Serializable {
val targetName: String
val executableName: String
val type: String // represents org.jetbrains.kotlin.konan.target.CompilerOutputKind
val targetPlatform: String
val file: File
val buildTaskPath: String
val runConfiguration: KonanRunConfigurationModel
val isTests: Boolean
}
interface KonanRunConfigurationModel : Serializable {
val workingDirectory: String
val programParameters: List<String>
val environmentVariables: Map<String, String>
fun isNotEmpty() = workingDirectory.isNotEmpty() || programParameters.isNotEmpty() || environmentVariables.isNotEmpty()
companion object {
const val NO_WORKING_DIRECTORY = ""
val NO_PROGRAM_PARAMETERS = emptyList<String>()
val NO_ENVIRONMENT_VARIABLES = emptyMap<String, String>()
}
}

View File

@@ -13,6 +13,8 @@ import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.logging.Logging
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Exec
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel.Companion.NO_KOTLIN_NATIVE_HOME
import org.jetbrains.plugins.gradle.model.*
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
@@ -218,6 +220,53 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
return project.getTargets()?.mapNotNull { buildTarget(it, sourceSetMap, dependencyResolver, project, dependencyMapper) }
}
private operator fun Any?.get(methodName: String, vararg params: Any): Any? {
return this[methodName, params.map { it.javaClass }, params.toList()]
}
private operator fun Any?.get(methodName: String, paramTypes: List<Class<*>>, params: List<Any?>): Any? {
if (this == null) return null
return this::class.java.getMethodOrNull(methodName, *paramTypes.toTypedArray())?.invoke(this, *params.toTypedArray())
}
private fun buildArtifact(
executableName: String,
linkTask: Task,
runConfiguration: KonanRunConfigurationModel
): KonanArtifactModel? {
val outputKind = linkTask["getOutputKind"]["name"] as? String ?: return null
val konanTargetName = linkTask["getTarget"] as? String ?: error("No arch target found")
val outputFile = (linkTask["getOutputFile"] as? Provider<*>)?.orNull as? File ?: return null
val compilationTarget = linkTask["getCompilation"]["getTarget"]
val compilationTargetName = compilationTarget["getName"] as? String ?: return null
val isTests = linkTask["getProcessTests"] as? Boolean ?: return null
return KonanArtifactModelImpl(
compilationTargetName,
executableName,
outputKind,
konanTargetName,
outputFile,
linkTask.path,
runConfiguration,
isTests
)
}
private fun konanArtifacts(target: Named): List<KonanArtifactModel> {
val result = ArrayList<KonanArtifactModel>()
val binaries = target["getBinaries"] as? Collection<*> ?: return result
binaries.forEach { binary ->
val executableName = binary["getBaseName"] as? String ?: ""
val linkTask = binary["getLinkTask"] as? Task ?: return@forEach
val runConfiguration = KonanRunConfigurationModelImpl(binary["getRunTask"] as? Exec)
buildArtifact(executableName, linkTask, runConfiguration)?.let { result.add(it) }
}
return result
}
private fun buildTarget(
gradleTarget: Named,
sourceSetMap: Map<String, KotlinSourceSet>,
@@ -247,7 +296,17 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
val jar = buildTargetJar(gradleTarget, project)
val testTasks = buildTestTasks(project, gradleTarget)
val target = KotlinTargetImpl(gradleTarget.name, targetPresetName, disambiguationClassifier, platform, compilations, testTasks, jar)
val artifacts = konanArtifacts(gradleTarget)
val target = KotlinTargetImpl(
gradleTarget.name,
targetPresetName,
disambiguationClassifier,
platform,
compilations,
testTasks,
jar,
artifacts
)
compilations.forEach {
it.disambiguationClassifier = target.disambiguationClassifier
it.platform = target.platform

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle
import org.gradle.api.tasks.Exec
import java.io.File
import kotlin.collections.HashSet
@@ -133,7 +134,8 @@ data class KotlinTargetImpl(
override val platform: KotlinPlatform,
override val compilations: Collection<KotlinCompilation>,
override val testTasks: Collection<KotlinTestTask>,
override val jar: KotlinTargetJar?
override val jar: KotlinTargetJar?,
override val konanArtifacts: List<KonanArtifactModel>
) : KotlinTarget {
override fun toString() = name
@@ -152,7 +154,8 @@ data class KotlinTargetImpl(
cloningCache[initialTestTask] = it
}
},
KotlinTargetJarImpl(target.jar?.archiveFile)
KotlinTargetJarImpl(target.jar?.archiveFile),
target.konanArtifacts.map { KonanArtifactModelImpl(it) }.toList()
)
}
@@ -209,3 +212,44 @@ class KotlinPlatformContainerImpl() : KotlinPlatformContainer {
(myPlatforms ?: HashSet<KotlinPlatform>().apply { myPlatforms = this }).addAll(platforms)
}
}
data class KonanArtifactModelImpl(
override val targetName: String,
override val executableName: String,
override val type: String,
override val targetPlatform: String,
override val file: File,
override val buildTaskPath: String,
override val runConfiguration: KonanRunConfigurationModel,
override val isTests: Boolean
) : KonanArtifactModel {
constructor(artifact: KonanArtifactModel) : this(
artifact.targetName,
artifact.executableName,
artifact.type,
artifact.targetPlatform,
artifact.file,
artifact.buildTaskPath,
KonanRunConfigurationModelImpl(artifact.runConfiguration),
artifact.isTests
)
}
data class KonanRunConfigurationModelImpl(
override val workingDirectory: String,
override val programParameters: List<String>,
override val environmentVariables: Map<String, String>
) : KonanRunConfigurationModel {
constructor(configuration: KonanRunConfigurationModel) : this(
configuration.workingDirectory,
ArrayList(configuration.programParameters),
HashMap(configuration.environmentVariables)
)
constructor(runTask: Exec?) : this(
runTask?.workingDir?.path ?: KonanRunConfigurationModel.NO_WORKING_DIRECTORY,
runTask?.args as List<String>? ?: KonanRunConfigurationModel.NO_PROGRAM_PARAMETERS,
(runTask?.environment as Map<String, Any>?)
?.mapValues { it.value.toString() } ?: KonanRunConfigurationModel.NO_ENVIRONMENT_VARIABLES
)
}

View File

@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.gradle
import org.gradle.api.Project
// KT-29613, KT-29783
internal object KotlinNativeHomeEvaluator {
object KotlinNativeHomeEvaluator {
private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome"
private const val FALLBACK_ACCESSOR_CLASS = "org.jetbrains.kotlin.compilerRunner.KotlinNativeToolRunnerKt"
private const val FALLBACK_ACCESSOR_METHOD = "getKonanHome"
internal fun getKotlinNativeHome(project: Project): String? =
fun getKotlinNativeHome(project: Project): String? =
getKotlinNativeHomePrimary(project) ?: getKotlinNativeHomeFallback(project)
// Read Kotlin/Native home from the predefined property in Gradle plugin.

View File

@@ -22,7 +22,7 @@ import org.junit.AfterClass
import java.io.File
/**
* inspired by @see AbstractCompletionHandlerTest
* inspired by @see AbstractCompletionHandlerTests
*/
abstract class AbstractPerformanceCompletionHandlerTests(
private val defaultCompletionType: CompletionType,
@@ -34,6 +34,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:"
private val TAIL_TEXT_PREFIX = "TAIL_TEXT:"
private val COMPLETION_CHAR_PREFIX = "CHAR:"
private val COMPLETION_CHARS_PREFIX = "CHARS:"
private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:"
companion object {
@@ -74,12 +75,10 @@ abstract class AbstractPerformanceCompletionHandlerTests(
val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX)
val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX)
val completionCharString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX)
val completionChar = when(completionCharString) {
"\\n", null -> '\n'
"\\t" -> '\t'
else -> completionCharString.singleOrNull() ?: error("Incorrect completion char: \"$completionCharString\"")
}
val completionChars = completionChars(
char = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX),
chars = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHARS_PREFIX)
)
val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType
@@ -102,7 +101,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
}
doPerfTestWithTextLoaded(
testPath, completionType, invocationCount, lookupString, itemText, tailText, completionChar
testPath, completionType, invocationCount, lookupString, itemText, tailText, completionChars
)
} finally {
if (configured) {
@@ -120,7 +119,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
lookupString: String?,
itemText: String?,
tailText: String?,
completionChar: Char
completionChars: String
) {
val testName = getTestName(false)
@@ -132,7 +131,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
setUpFixture(testPath)
},
test = {
perfTestCore(completionType, time, lookupString, itemText, tailText, completionChar)
perfTestCore(completionType, time, lookupString, itemText, tailText, completionChars)
},
tearDown = {
runWriteAction {
@@ -147,14 +146,20 @@ abstract class AbstractPerformanceCompletionHandlerTests(
lookupString: String?,
itemText: String?,
tailText: String?,
completionChar: Char
completionChars: String
) {
completionChars?.let {
for (idx in 0 until it.length - 1) {
fixture.type(it[idx])
}
}
fixture.complete(completionType, time)
if (lookupString != null || itemText != null || tailText != null) {
val item = getExistentLookupElement(lookupString, itemText, tailText)
if (item != null) {
selectItem(item, completionChar)
selectItem(item, completionChars.last())
}
}
}

View File

@@ -103,6 +103,16 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
}
}
protected fun warmUpProject(stats: Stats) {
val project = innerPerfOpenProject("helloKotlin", stats, "warm-up")
try {
val perfHighlightFile = perfHighlightFile(project, "src/HelloMain.kt", stats, "warm-up")
assertTrue("kotlin project has been not imported properly", perfHighlightFile.isNotEmpty())
} finally {
closeProject(project)
}
}
override fun tearDown() {
RunAll(
ThrowableRunnable { super.tearDown() },
@@ -122,6 +132,9 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
return if (lastIndexOf >= 0) fileName.substring(lastIndexOf + 1) else fileName
}
protected fun perfOpenKotlinProject(stats: Stats) =
perfOpenProject("perfTestProject", stats = stats, path = "..")
protected fun perfOpenProject(name: String, stats: Stats, path: String = "idea/testData/perfTest") {
myProject = innerPerfOpenProject(name, stats, path = path, note = "")
}
@@ -291,8 +304,8 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
stats: Stats,
note: String = ""
): List<HighlightInfo> {
var highlightInfos: List<HighlightInfo> = emptyList()
IdentifierHighlighterPassFactory.doWithHighlightingEnabled {
return highlightFile {
var highlightInfos: List<HighlightInfo> = emptyList()
stats.perfTest<EditorFile, List<HighlightInfo>>(
testName = "highlighting ${if (note.isNotEmpty()) "$note " else ""}${simpleFilename(fileName)}",
setUp = {
@@ -309,9 +322,21 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
PsiManager.getInstance(project).dropPsiCaches()
}
)
highlightInfos
}
//println("${"-".repeat(40)}\n$fileName ->\n${highlightInfos.joinToString("\n")}\n")
}
fun highlightFile(psiFile: PsiFile): List<HighlightInfo> {
return highlightFile {
highlightFile(myProject!!, psiFile)
}
}
private fun highlightFile(block: () -> List<HighlightInfo>): List<HighlightInfo> {
var highlightInfos: List<HighlightInfo> = emptyList()
IdentifierHighlighterPassFactory.doWithHighlightingEnabled {
highlightInfos = block()
}
return highlightInfos
}
@@ -392,7 +417,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
}
}
private fun openFileInEditor(project: Project, name: String): EditorFile {
fun openFileInEditor(project: Project, name: String): EditorFile {
val fileDocumentManager = FileDocumentManager.getInstance()
val fileEditorManager = FileEditorManager.getInstance(project)
@@ -421,6 +446,6 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
return virtualFile!!.toPsiFile(project)!!
}
private data class EditorFile(val psiFile: PsiFile, val document: Document)
data class EditorFile(val psiFile: PsiFile, val document: Document)
}

View File

@@ -26,7 +26,7 @@ public class PerformanceCompletionCharFilterTestGenerated extends AbstractPerfor
}
public void testAllFilesPresentInCharFilter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Colon.kt")
@@ -144,6 +144,11 @@ public class PerformanceCompletionCharFilterTestGenerated extends AbstractPerfor
runTest("idea/idea-completion/testData/handlers/charFilter/LParenth.kt");
}
@TestMetadata("MessageBundle1.kt")
public void testMessageBundle1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/MessageBundle1.kt");
}
@TestMetadata("NamedParameter1.kt")
public void testNamedParameter1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/NamedParameter1.kt");

View File

@@ -35,10 +35,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
super.setUp()
// warm up: open simple small project
if (!warmedUp) {
val project = innerPerfOpenProject("helloKotlin", hwStats, "warm-up")
val perfHighlightFile = perfHighlightFile(project, "src/HelloMain.kt", hwStats, "warm-up")
assertTrue("kotlin project has been not imported properly", perfHighlightFile.isNotEmpty())
closeProject(project)
warmUpProject(hwStats)
warmedUp = true
}
@@ -58,7 +55,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
tcSuite("Kotlin project") {
val stats = Stats("kotlin project")
stats.use {
perfOpenProject("perfTestProject", stats = it, path = "..")
perfOpenKotlinProject(it)
perfHighlightFile("compiler/psi/src/org/jetbrains/kotlin/psi/KtFile.kt", stats = it)
@@ -71,7 +68,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
tcSuite("Kotlin project highlight build gradle") {
val stats = Stats("kotlin project highlight build gradle")
stats.use {
perfOpenProject("perfTestProject", stats = it, path = "..")
perfOpenKotlinProject(it)
enableAnnotatorsAndLoadDefinitions()

View File

@@ -52,6 +52,9 @@
<extensionPoint qualifiedName="org.jetbrains.kotlin.j2kConverterExtension"
interface="org.jetbrains.kotlin.j2k.J2kConverterExtension"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.scriptDiagnosticFixProvider"
interface="org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="org.jetbrains.kotlin">

View File

@@ -60,6 +60,9 @@
<extensionPoint qualifiedName="org.jetbrains.kotlin.j2kConverterExtension"
interface="org.jetbrains.kotlin.j2k.J2kConverterExtension"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.scriptDiagnosticFixProvider"
interface="org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="org.jetbrains.kotlin">

View File

@@ -47,11 +47,14 @@
interface="org.jetbrains.kotlin.synthetic.SyntheticScopeProviderExtension"
area="IDEA_PROJECT"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.resolveScopeEnlarger"
interface="org.jetbrains.kotlin.idea.caches.resolve.util.KotlinResolveScopeEnlarger"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.j2kConverterExtension"
interface="org.jetbrains.kotlin.j2k.J2kConverterExtension"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.resolveScopeEnlarger"
interface="org.jetbrains.kotlin.idea.caches.resolve.util.KotlinResolveScopeEnlarger"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.scriptDiagnosticFixProvider"
interface="org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="org.jetbrains.kotlin">

View File

@@ -47,11 +47,14 @@
interface="org.jetbrains.kotlin.synthetic.SyntheticScopeProviderExtension"
area="IDEA_PROJECT"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.resolveScopeEnlarger"
interface="org.jetbrains.kotlin.idea.caches.resolve.util.KotlinResolveScopeEnlarger"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.j2kConverterExtension"
interface="org.jetbrains.kotlin.j2k.J2kConverterExtension"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.resolveScopeEnlarger"
interface="org.jetbrains.kotlin.idea.caches.resolve.util.KotlinResolveScopeEnlarger"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.scriptDiagnosticFixProvider"
interface="org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="org.jetbrains.kotlin">

View File

@@ -1,8 +1,10 @@
<idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>

View File

@@ -1,8 +1,10 @@
<idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>

View File

@@ -1,8 +1,10 @@
<idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>

View File

@@ -1,8 +1,10 @@
<idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>

View File

@@ -9,6 +9,7 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
<scriptDiagnosticFixProvider implementation="org.jetbrains.kotlin.idea.script.GradleScriptDiagnosticFixProvider"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
@@ -22,4 +23,10 @@
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectSettingsDataService"/>
</extensions>
<actions>
<action id="Kotlin.Gradle.ShowDslLogs" class="org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs"
text="Show Kotlin Gradle DSL Logs" description="Show Kotlin Gradle DSL logs">
</action>
</actions>
</idea-plugin>

View File

@@ -9,6 +9,7 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
<scriptDiagnosticFixProvider implementation="org.jetbrains.kotlin.idea.script.GradleScriptDiagnosticFixProvider"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
@@ -21,4 +22,10 @@
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectSettingsDataService"/>
</extensions>
<actions>
<action id="Kotlin.Gradle.ShowDslLogs" class="org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs"
text="Show Kotlin Gradle DSL Logs" description="Show Kotlin Gradle DSL logs">
</action>
</actions>
</idea-plugin>

View File

@@ -129,6 +129,7 @@
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.configuration.KotlinSetupEnvironmentNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinAlternativeSourceNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.inspections.JavaOutsideModuleDetector"/>
<consoleFilterProvider implementation="org.jetbrains.kotlin.idea.run.KotlinConsoleFilterProvider"/>
@@ -192,7 +193,7 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<diagnosticSuppressor implementation="org.jetbrains.kotlin.idea.debugger.DiagnosticSuppressorForDebugger"/>
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
@@ -211,12 +212,6 @@
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJSFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleGroovyFrameworkSupportProvider" />
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JsIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
<syntheticScopeProviderExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldSyntheticScopeProvider"/>
<expressionCodegenExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldExpressionCodegenExtension"/>
<completionInformationProvider implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldCompletionInformationProvider" />

View File

@@ -128,6 +128,7 @@
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.configuration.KotlinSetupEnvironmentNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinAlternativeSourceNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.inspections.JavaOutsideModuleDetector"/>
<consoleFilterProvider implementation="org.jetbrains.kotlin.idea.run.KotlinConsoleFilterProvider"/>
@@ -186,7 +187,7 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<diagnosticSuppressor implementation="org.jetbrains.kotlin.idea.debugger.DiagnosticSuppressorForDebugger"/>
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
@@ -205,12 +206,6 @@
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJSFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleGroovyFrameworkSupportProvider" />
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JsIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
<syntheticScopeProviderExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldSyntheticScopeProvider"/>
<expressionCodegenExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldExpressionCodegenExtension"/>
<completionInformationProvider implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldCompletionInformationProvider" />

View File

@@ -129,6 +129,7 @@
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.configuration.KotlinSetupEnvironmentNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinAlternativeSourceNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.inspections.JavaOutsideModuleDetector"/>
<consoleFilterProvider implementation="org.jetbrains.kotlin.idea.run.KotlinConsoleFilterProvider"/>
@@ -187,7 +188,7 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<diagnosticSuppressor implementation="org.jetbrains.kotlin.idea.debugger.DiagnosticSuppressorForDebugger"/>
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
@@ -206,12 +207,6 @@
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJSFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleGroovyFrameworkSupportProvider" />
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JsIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
<syntheticScopeProviderExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldSyntheticScopeProvider"/>
<expressionCodegenExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldExpressionCodegenExtension"/>
<completionInformationProvider implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldCompletionInformationProvider" />

View File

@@ -3396,11 +3396,10 @@
groupPath="Kotlin"
groupName="Style issues"
enabledByDefault="true"
level="WEAK WARNING"
level="INFORMATION"
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantEmptyInitializerBlockInspection"
displayName="Redundant empty initializer block"
groupPath="Kotlin"
@@ -3466,4 +3465,13 @@
<navbar implementation="org.jetbrains.kotlin.idea.navigationToolbar.KotlinNavBarModelExtension" order="first"/>
</extensions>
</idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JsIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
</extensions>
</idea-plugin>

View File

@@ -36,31 +36,64 @@ import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
// Based on com.intellij.refactoring.OptimizeImportsRefactoringHelper
class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper<Set<KtFile>> {
internal class OptimizeImportsTask(
private val task: SequentialModalProgressTask,
pointers: Set<SmartPsiElementPointer<KtImportDirective>>
internal class CollectUnusedImportsTask(
private val task: SequentialModalProgressTask,
private val dumbService: DumbService,
private val unusedImports: MutableSet<SmartPsiElementPointer<KtImportDirective>>,
operationData: Set<KtFile>
) : SequentialTask {
private val pointerIterator = pointers.iterator()
private val myTotalCount = operationData.size
private val operationIterator = operationData.withIndex().iterator()
override fun prepare() {}
override fun stop() {}
override fun isDone(): Boolean = !operationIterator.hasNext()
override fun iteration(): Boolean {
val (counter, file) = operationIterator.next()
if (!file.isValid) return isDone
val virtualFile = file.virtualFile ?: return isDone
with(task.indicator) {
text2 = virtualFile.presentableUrl
fraction = counter.toDouble() / myTotalCount
}
dumbService.runReadActionInSmartMode {
KotlinUnusedImportInspection.analyzeImports(file)?.unusedImports?.mapTo(unusedImports) { it.createSmartPointer() }
}
return isDone
}
}
internal class OptimizeImportsTask(
private val task: SequentialModalProgressTask,
pointers: Set<SmartPsiElementPointer<KtImportDirective>>
) : SequentialTask {
private val pointerIterator = pointers.withIndex().iterator()
private val myTotal: Int = pointers.size
private var myCount: Int = 0
override fun prepare() {}
override fun isDone() = !pointerIterator.hasNext()
override fun iteration(): Boolean {
task.indicator?.fraction = myCount++.toDouble() / myTotal
val (counter, pointer) = pointerIterator.next()
val pointer = pointerIterator.next()
task.indicator?.fraction = counter.toDouble() / myTotal
val directive = pointer.element
if (directive == null || !directive.isValid) return isDone
try {
directive.delete()
}
catch (e: IncorrectOperationException) {
LOG.error(e)
if (directive?.isValid == true) {
task.indicator?.text2 = directive.containingFile.virtualFile.presentableUrl
runWriteAction {
try {
directive.delete()
} catch (e: IncorrectOperationException) {
LOG.error(e)
}
}
}
return isDone
@@ -74,7 +107,8 @@ class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper<Set<KtFile>> {
}
companion object {
private val REMOVING_REDUNDANT_IMPORTS_TITLE = "Removing redundant imports"
private const val COLLECT_UNUSED_IMPORTS_TITLE = "Collect unused imports"
private const val REMOVING_REDUNDANT_IMPORTS_TITLE = "Removing redundant imports"
}
override fun prepareOperation(usages: Array<UsageInfo>): Set<KtFile> {
@@ -90,33 +124,26 @@ class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper<Set<KtFile>> {
if (operationData.isEmpty()) return
val unusedImports = LinkedHashSet<SmartPsiElementPointer<KtImportDirective>>()
val findRedundantImports = {
DumbService.getInstance(project).runReadActionInSmartMode {
val progressIndicator = ProgressManager.getInstance().progressIndicator
val fileCount = operationData.size
for ((i, file) in operationData.withIndex()) {
if (!file.isValid) continue
val virtualFile = file.virtualFile ?: continue
val unusedImports = mutableSetOf<SmartPsiElementPointer<KtImportDirective>>()
progressIndicator?.text2 = virtualFile.presentableUrl
progressIndicator?.fraction = i.toDouble() / fileCount
val progressManager = ProgressManager.getInstance()
val fileImportData = KotlinUnusedImportInspection.analyzeImports(file) ?: continue
fileImportData.unusedImports.mapTo(unusedImports) { it.createSmartPointer() }
val dumbService = DumbService.getInstance(project)
val collectTask = object : SequentialModalProgressTask(project, COLLECT_UNUSED_IMPORTS_TITLE, false) {
override fun onSuccess() {
val progressTask = SequentialModalProgressTask(project, REMOVING_REDUNDANT_IMPORTS_TITLE, false)
with(progressTask) {
setMinIterationTime(200)
setTask(OptimizeImportsTask(this, unusedImports))
}
progressManager.run(progressTask)
}
}
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
findRedundantImports, REMOVING_REDUNDANT_IMPORTS_TITLE, false, project
)) return
runWriteAction {
val progressTask = SequentialModalProgressTask(project, REMOVING_REDUNDANT_IMPORTS_TITLE, false).apply {
setMinIterationTime(200)
setTask(OptimizeImportsTask(this, unusedImports))
}
ProgressManager.getInstance().run(progressTask)
with(collectTask) {
setMinIterationTime(200)
setTask(CollectUnusedImportsTask(this, dumbService, unusedImports, operationData))
}
progressManager.run(collectTask)
}
}

View File

@@ -11,6 +11,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
import org.jetbrains.kotlin.idea.caches.resolve.analyze
@@ -31,7 +32,8 @@ class RemoveRedundantQualifierNameInspection : AbstractKotlinInspection(), Clean
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor =
object : KtVisitorVoid() {
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) {
if (expression.parent is KtDotQualifiedExpression || expression.isInImportDirective()) return
val expressionParent = expression.parent
if (expressionParent is KtDotQualifiedExpression || expressionParent is KtPackageDirective || expressionParent is KtImportDirective) return
val expressionForAnalyze = expression.firstExpressionWithoutReceiver() ?: return
val parent = expressionForAnalyze.parent
@@ -72,7 +74,8 @@ private tailrec fun KtDotQualifiedExpression.firstExpressionWithoutReceiver(): K
val element = getQualifiedElementSelector()?.mainReference?.resolve() ?: return null
return if (element is KtClassOrObject ||
element is KtCallableDeclaration && element.receiverTypeReference == null ||
element is PsiMember && element.hasModifier(JvmModifier.STATIC)
element is PsiMember && element.hasModifier(JvmModifier.STATIC) ||
element is PsiMethod && element.isConstructor
) this else (receiverExpression as? KtDotQualifiedExpression)?.firstExpressionWithoutReceiver()
}

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