Compare commits

...

36 Commits

Author SHA1 Message Date
nikita.movshin
f0555ab5df Fix changelog for 1.3.40 2019-05-17 20:59:49 +03:00
nikita.movshin
cac8f3ace3 Add changelog for 1.3.40 2019-05-17 20:57:41 +03:00
Elena Lepilkina
d331c7d376 New EAP buikd of Kotlin/Native 2019-05-17 10:17:53 +03:00
Roman Artemev
ad4671ed5f [IR BE] Delegate coroutine naming strategy to platform part
(cherry picked from commit 02d84bf061)
2019-05-16 19:20:41 +03:00
Alexey Tsvetkov
7cc4c606a1 Do not expose paths with placeholders in JS IC caches
#KT-31310 Fixed
2019-05-16 04:07:14 +03:00
Elena Lepilkina
009e33ed72 Changed Kotlin/Native version (EAP1) 2019-05-15 12:09:26 +03:00
Dmitry Gridin
2d83ceb980 Fix "Unused import" for 'provideDelegate'
#KT-31319 Fixed

(cherry picked from commit eee8d0263d)
2019-05-14 22:02:23 +07:00
Dmitry Gridin
966dd3ee24 Don't delete import from stdlib if alias exists and used
#KT-31414 Fixed

(cherry picked from commit 3914530fa8)
2019-05-14 22:02:07 +07:00
Dmitry Gridin
efdb19772b Optimize Imports shouldn't delete imports with unresolved parts
#KT-10512 Fixed

(cherry picked from commit 32298522dd)
2019-05-14 22:01:42 +07:00
Ilya Gorbunov
7accee269b Add simplified overloads of String<->ByteArray/CharArray conversions
These overloads cover the most common cases of conversion of the entire
String or Byte/CharArray, avoiding extra index check and branching.

#KT-24810, KT-29265

(cherry picked from commit 2c26dc3af6)
2019-05-14 17:54:13 +03:00
Mikhail Glukhikh
012b8f76a0 Fix .inspection file for ConvertNaNEquality tests
(cherry picked from commit 2d5f41cfe3)
2019-05-14 16:50:51 +03:00
Matthew Runo
01551d1bad Migrate RetentionPolicy arguments in deprecated Java quick-fix
#KT-29666 Fixed

(cherry picked from commit 39f576d75c)
2019-05-14 09:28:49 +03:00
Toshiaki Kameyama
be2c670c09 Implicit Nothing? type: don't report when declaration overrides nullable nothing type
#KT-30481 Fixed

(cherry picked from commit 14259ca9e0)
2019-05-14 09:28:23 +03:00
Dereck Bridie
a3ebd0751c KT-26629 Inspection to replace equality check with NaN with isNaN call
(cherry picked from commit 574178882a)
2019-05-14 09:27:58 +03:00
Mikhail Glukhikh
9d013254a4 Add name to argument: support old-style comment deletion
(cherry picked from commit b4a63794e5)
2019-05-14 09:27:36 +03:00
Mikhail Glukhikh
15045d2512 Use candidate descriptor to determine parameter name stability in IDEA
#KT-31349 Fixed

(cherry picked from commit b0d294b50c)
2019-05-14 09:27:12 +03:00
Mikhail Glukhikh
fa9cf694dd Apply "unnamed boolean literal" to idea & J2K + other style fixes
(cherry picked from commit d517276a06)
2019-05-14 09:26:51 +03:00
Mikhail Glukhikh
d849bde003 Introduce "add parameter names to following arguments"
This commit also refactors relevant intentions & inspections,
like "add name to argument", "add names to call arguments",
"unnamed boolean literal argument"

#KT-30622 Fixed

(cherry picked from commit 955bfd6e7b)
2019-05-14 09:26:25 +03:00
Sergey Igushkin
5694726f04 Introduce Java support in JVM MPP targets (KT-26256)
Deprecate the `jvmWithJava` preset, add warning.

Add a function `withJava()` to JVM MPP targets which applies the 'java'
plugin and sets up the Kotlin & Java interoperation.

Issue #KT-26256 Fixed

Signed-off-by: Sergey Igushkin <hotkeytlt@gmail.com>
(cherry picked from commit be05095df5)
2019-05-13 18:11:04 +03:00
Mikhail Zarechenskiy
d277ddb38c [NI] Complete call if return type contains only "good" type variables 2019-05-13 16:21:01 +03:00
Mikhail Zarechenskiy
3d6c735538 [NI] Complete call if return type has proper lower or equal constraints
There was a silly bug: equal constraint is actually a lower and an upper
 constraint, but we checked only presence of lower constraints.

 Test is important as here we have one equal constraint and should
 complete inner call `foo<Int>()` without propagating it to `bar` to
 avoid using `NoInfer` annotation multiple times
2019-05-13 16:20:52 +03:00
Mikhail Zarechenskiy
8165d07346 [NI] Use original implicit receiver for DSL violation check
There is an inconsistency between old and new inference for storing
 receivers of resolved calls. In new inference, for captured types,
 receiver will be changed and to preserve behavior of the old inference,
 we use original one during important checks.
 This is more a workaround than a solution and should be revisited.

 #KT-31356 Fixed
 #KT-29948 Fixed
 #KT-31360 Fixed
2019-05-13 16:20:43 +03:00
Mikhail Zarechenskiy
2a58d137e2 [NI] Preserve annotations during type substitution
#KT-31346 Fixed
2019-05-13 16:20:34 +03:00
Toshiaki Kameyama
b6f2cc125a "Redundant 'requireNotNull' or 'checkNotNull' call": don't remove first argument if function is used as expression
#KT-31404 Fixed

(cherry picked from commit cf4471ba53)
2019-05-13 17:05:02 +07:00
Dmitry Gridin
40f2823278 Fix incorrect quickfix "Replace with Kotlin analog" for conversion to an extension
where the first argument is an expression with an operation
 #KT-31341 Fixed

(cherry picked from commit 07e908f15f)
2019-05-13 17:04:49 +07:00
Natalia Selezneva
aa6d3c3fbe Fix NPE in SLRUMap in ScriptDefinitionsManager
EA-138364 - NPE: LinkedHashMap$Entry.access$

(cherry picked from commit e158875a14)
2019-05-13 12:39:50 +03:00
Natalia Selezneva
469230016e Do not provide 'add dependency' quick fix for unresolved references for non-project files
EA-126105 - NPE: JavaFileManagerImpl$LibSrcExcludingScope.<init> (KotlinAddOrderEntryActionFactory)

(cherry picked from commit 2a2fe6b428)
2019-05-13 12:39:13 +03:00
Natalia Selezneva
ce55ae31b5 Fix 'Invalid file' Exception during script definition search (EA-125840)
EA-125840 - assert: FileManagerImpl.findFile

(cherry picked from commit ba7d66eb4b)
2019-05-13 12:38:49 +03:00
Natalia Selezneva
703dd28553 Do not use canonical paths in OutsidersPsiFileSupportUtils (EA-135551)
EA-135551 - IOE: OutsidersPsiFileSupportUtils$getOutsiderFileOrigin$.invoke

(cherry picked from commit 836006b3f3)
2019-05-13 12:38:28 +03:00
Natalia Selezneva
3249a82f33 Fix notification about highlighting for diff view in build.gradle.kts (KT-30638)
(cherry picked from commit 98235952ad)

^KT-30638 Fixed
2019-05-13 12:38:02 +03:00
Natalia Selezneva
c5d590cbfd Fix highlighting for scripts in diff view (KT-30690)
(cherry picked from commit 495d98f997)

^KT-30690 Fixed
2019-05-13 12:37:00 +03:00
Natalia Selezneva
1fe369bf84 Minor: extract common parts
(cherry picked from commit 88c6ecbbdf)
2019-05-13 12:36:28 +03:00
Natalia Selezneva
33246782dc Run indexes update after typing in script if needed
(cherry picked from commit 89bf7f991a)
2019-05-13 12:36:02 +03:00
Natalia Selezneva
49c539eb39 Refactoring: add isApplicable method to ScriptDependenciesLoader
(cherry picked from commit 9e51f82248)
2019-05-13 12:35:32 +03:00
Natalia Selezneva
1a8dbc07ed Do not start script dependencies update if dependencies are already cached
(cherry picked from commit e990c61b55)
2019-05-13 12:35:08 +03:00
LepilkinaElena
6c0750e975 Version of K/N for MPP is set to EAP0 version 2019-05-07 14:50:59 +03:00
216 changed files with 2653 additions and 8552 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -114,8 +114,7 @@ open class IncrementalJsCache(
fun nonDirtyPackageParts(): Map<File, TranslationResultValue> =
hashMapOf<File, TranslationResultValue>().apply {
for (path in translationResults.keys()) {
val file = File(path)
for (file in translationResults.keys()) {
if (file !in dirtySources) {
put(file, translationResults[file]!!)
}
@@ -167,8 +166,8 @@ private class TranslationResultMap(
operator fun get(sourceFile: File): TranslationResultValue? =
storage[pathConverter.toPath(sourceFile)]
fun keys(): Collection<String> =
storage.keys
fun keys(): Collection<File> =
storage.keys.map { pathConverter.toFile(it) }
fun remove(sourceFile: File, changesCollector: ChangesCollector) {
val path = pathConverter.toPath(sourceFile)

View File

@@ -158,7 +158,7 @@ extra["versions.trove4j"] = "1.0.20181211"
extra["versions.kotlin-native-shared"] = "1.0-dev-50"
if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.3-dev-9780"
extra["versions.kotlin-native"] = "1.3-eap-10124"
}
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null

View File

@@ -300,7 +300,7 @@ class Fir2IrDeclarationStorage(
startOffset, endOffset, origin, symbol,
constructor.name, constructor.visibility,
constructor.returnTypeRef.toIrType(session, this),
false, false, isPrimary
isInline = false, isExternal = false, isPrimary = isPrimary
).bindAndDeclareParameters(constructor, descriptor, setParent, shouldLeaveScope)
}
}

View File

@@ -167,18 +167,18 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
callableName,
ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
ProtoEnumFlags.modality(Flags.MODALITY.get(flags)),
Flags.IS_EXPECT_PROPERTY.get(flags),
false,
false,
Flags.IS_CONST.get(flags),
Flags.IS_LATEINIT.get(flags),
proto.receiverType(c.typeTable)?.toTypeRef(local),
returnTypeRef,
Flags.IS_VAR.get(flags),
null,
FirDefaultPropertyGetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))),
FirDefaultPropertySetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))),
null
isExpect = Flags.IS_EXPECT_PROPERTY.get(flags),
isActual = false,
isOverride = false,
isConst = Flags.IS_CONST.get(flags),
isLateInit = Flags.IS_LATEINIT.get(flags),
receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local),
returnTypeRef = returnTypeRef,
isVar = Flags.IS_VAR.get(flags),
initializer = null,
getter = FirDefaultPropertyGetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))),
setter = FirDefaultPropertySetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))),
delegate = null
).apply {
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.firUnsafe() }
annotations += c.annotationDeserializer.loadPropertyAnnotations(proto, local.nameResolver)
@@ -209,16 +209,16 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
ProtoEnumFlags.modality(Flags.MODALITY.get(flags)),
Flags.IS_EXPECT_FUNCTION.get(flags),
false,
false,
Flags.IS_OPERATOR.get(flags),
Flags.IS_INFIX.get(flags),
Flags.IS_INLINE.get(flags),
Flags.IS_TAILREC.get(flags),
Flags.IS_EXTERNAL_FUNCTION.get(flags),
Flags.IS_SUSPEND.get(flags),
proto.receiverType(local.typeTable)?.toTypeRef(local),
proto.returnType(local.typeTable).toTypeRef(local)
isActual = false,
isOverride = false,
isOperator = Flags.IS_OPERATOR.get(flags),
isInfix = Flags.IS_INFIX.get(flags),
isInline = Flags.IS_INLINE.get(flags),
isTailRec = Flags.IS_TAILREC.get(flags),
isExternal = Flags.IS_EXTERNAL_FUNCTION.get(flags),
isSuspend = Flags.IS_SUSPEND.get(flags),
receiverTypeRef = proto.receiverType(local.typeTable)?.toTypeRef(local),
returnTypeRef = proto.returnType(local.typeTable).toTypeRef(local)
).apply {
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.firUnsafe() }
valueParameters += local.memberDeserializer.valueParameters(proto.valueParameterList)

View File

@@ -22,7 +22,11 @@ interface SyntheticSymbol : ConeSymbol
class SyntheticPropertySymbol(callableId: CallableId) : FirPropertySymbol(callableId), SyntheticSymbol
class FirSyntheticPropertiesScope(val session: FirSession, val baseScope: FirScope, val typeCalculator: ReturnTypeCalculator) : FirScope {
class FirSyntheticPropertiesScope(
val session: FirSession,
private val baseScope: FirScope,
private val typeCalculator: ReturnTypeCalculator
) : FirScope {
val synthetic: MutableMap<ConeCallableSymbol, ConeVariableSymbol> = mutableMapOf()
@@ -47,18 +51,18 @@ class FirSyntheticPropertiesScope(val session: FirSession, val baseScope: FirSco
name,
fir.visibility,
fir.modality,
false,
false,
false,
false,
false,
null,
returnTypeRef,
true,
null,
FirDefaultPropertyGetter(session, null, returnTypeRef, fir.visibility),
FirDefaultPropertySetter(session, null, returnTypeRef, fir.visibility),
null
isExpect = false,
isActual = false,
isOverride = false,
isConst = false,
isLateInit = false,
receiverTypeRef = null,
returnTypeRef = returnTypeRef,
isVar = true,
initializer = null,
getter = FirDefaultPropertyGetter(session, null, returnTypeRef, fir.visibility),
setter = FirDefaultPropertySetter(session, null, returnTypeRef, fir.visibility),
delegate = null
)
return processor(synthetic)
}

View File

@@ -169,9 +169,9 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider
relativeClassName.shortName(),
Visibilities.PUBLIC,
Modality.OPEN,
false,
false,
ClassKind.CLASS,
isExpect = false,
isActual = false,
classKind = ClassKind.CLASS,
isInner = false,
isCompanion = false,
isData = false,

View File

@@ -435,10 +435,10 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
null,
Name.identifier("it"),
FirResolvedTypeRefImpl(session, null, parameters.single(), emptyList()),
null,
false,
false,
false
defaultValue = null,
isCrossinline = false,
isNoinline = false,
isVararg = false
)
else -> null
}

View File

@@ -17470,6 +17470,21 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/insideTopLevelExtensionAnnotatedType.kt");
}
@TestMetadata("kt29948.kt")
public void testKt29948() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt29948.kt");
}
@TestMetadata("kt31360.kt")
public void testKt31360() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt31360.kt");
}
@TestMetadata("markedReceiverWithCapturedTypeArgument.kt")
public void testMarkedReceiverWithCapturedTypeArgument() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/markedReceiverWithCapturedTypeArgument.kt");
}
@TestMetadata("markersIntersection.kt")
public void testMarkersIntersection() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/markersIntersection.kt");

View File

@@ -53,14 +53,14 @@ class DelegatedPropertyInferenceSession(
?: builtIns.nullableNothingType
val valueParameterForThis = descriptor.valueParameters.getOrNull(0) ?: return
val substitutedType = substitutor.substituteKeepAnnotations(valueParameterForThis.type.unwrap())
val substitutedType = substitutor.safeSubstitute(valueParameterForThis.type.unwrap())
commonSystem.addSubtypeConstraint(typeOfThis.unwrap(), substitutedType, DelegatedPropertyConstraintPosition(atom))
}
private fun ResolvedCallAtom.addConstraintsForGetValueMethod(commonSystem: ConstraintSystemBuilder) {
if (expectedType != null) {
val unsubstitutedReturnType = candidateDescriptor.returnType?.unwrap() ?: return
val substitutedReturnType = substitutor.substituteKeepAnnotations(unsubstitutedReturnType)
val substitutedReturnType = substitutor.safeSubstitute(unsubstitutedReturnType)
commonSystem.addSubtypeConstraint(substitutedReturnType, expectedType, DelegatedPropertyConstraintPosition(atom))
}
@@ -71,7 +71,7 @@ class DelegatedPropertyInferenceSession(
private fun ResolvedCallAtom.addConstraintsForSetValueMethod(commonSystem: ConstraintSystemBuilder) {
if (expectedType != null) {
val unsubstitutedParameterType = candidateDescriptor.valueParameters.getOrNull(2)?.type?.unwrap() ?: return
val substitutedParameterType = substitutor.substituteKeepAnnotations(unsubstitutedParameterType)
val substitutedParameterType = substitutor.safeSubstitute(unsubstitutedParameterType)
commonSystem.addSubtypeConstraint(expectedType, substitutedParameterType, DelegatedPropertyConstraintPosition(atom))
}

View File

@@ -31,7 +31,12 @@ object DslScopeViolationCallChecker : CallChecker {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.DslMarkersSupport)) return
val callImplicitReceivers = resolvedCall.getImplicitReceivers()
for (callImplicitReceiver in callImplicitReceivers) {
val originalReceivers = if (context.languageVersionSettings.supportsFeature(LanguageFeature.NewInference))
callImplicitReceivers.map { it.original }
else
callImplicitReceivers
for (callImplicitReceiver in originalReceivers) {
checkCallImplicitReceiver(callImplicitReceiver, resolvedCall, reportOn, context)
}
}

View File

@@ -91,6 +91,7 @@ class KotlinResolutionCallbacksImpl(
receiverType: UnwrappedType?,
parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType?,
annotations: Annotations,
stubsForPostponedVariables: Map<NewTypeVariable, StubType>
): Pair<List<KotlinCallArgument>, InferenceSession?> {
val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument
@@ -130,7 +131,7 @@ class KotlinResolutionCallbacksImpl(
val builtIns = outerCallContext.scope.ownerDescriptor.builtIns
val expectedType = createFunctionType(
builtIns, Annotations.EMPTY, receiverType, parameters, null,
builtIns, annotations, receiverType, parameters, null,
lambdaInfo.expectedType, isSuspend
)

View File

@@ -191,8 +191,8 @@ class ResolvedAtomCompleter(
val substitutedFunctionalType = createFunctionType(
builtIns,
existingLambdaType.annotations,
lambda.receiver?.let { resultSubstitutor.substituteKeepAnnotations(it) },
lambda.parameters.map { resultSubstitutor.substituteKeepAnnotations(it) },
lambda.receiver?.let { resultSubstitutor.safeSubstitute(it) },
lambda.parameters.map { resultSubstitutor.safeSubstitute(it) },
null, // parameter names transforms to special annotations, so they are already taken from parameter types
returnType,
lambda.isSuspend
@@ -208,7 +208,7 @@ class ResolvedAtomCompleter(
}
val valueType = receiver.value.type.unwrap()
val newValueType = resultSubstitutor.substituteKeepAnnotations(valueType)
val newValueType = resultSubstitutor.safeSubstitute(valueType)
if (valueType !== newValueType) {
val newReceiverValue = receiver.value.replaceType(newValueType)

View File

@@ -33,7 +33,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
protected abstract val stateMachineMethodName: Name
protected abstract fun getCoroutineBaseClass(function: IrFunction): IrClassSymbol
protected abstract fun nameForCoroutineClass(function: IrFunction): Name
protected abstract fun buildStateMachine(
originalBody: IrBody, stateMachineFunction: IrFunction,
@@ -258,8 +258,6 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
val stateMachineFunction: IrFunction
)
private var coroutineId = 0
private inner class CoroutineBuilder(val irFunction: IrFunction, val functionReference: IrFunctionReference?) {
private val startOffset = irFunction.startOffset
@@ -273,7 +271,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
startOffset, endOffset,
DECLARATION_ORIGIN_COROUTINE_IMPL,
IrClassSymbolImpl(d),
"${irFunction.name}COROUTINE\$${coroutineId++}".synthesizedName,
nameForCoroutineClass(irFunction),
ClassKind.CLASS,
irFunction.visibility,
Modality.FINAL,

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.ir.isSuspend
import org.jetbrains.kotlin.backend.common.lower.AbstractSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.IrElement
@@ -34,10 +35,13 @@ class JsSuspendFunctionsLowering(ctx: JsIrBackendContext) : AbstractSuspendFunct
private val coroutineImplResultSymbolSetter = ctx.coroutineImplResultSymbolSetter
private var exceptionTrapId = -1
private var coroutineId = 0
override val stateMachineMethodName = Name.identifier("doResume")
override fun getCoroutineBaseClass(function: IrFunction) = context.ir.symbols.coroutineImpl
override fun nameForCoroutineClass(function: IrFunction) = "${function.name}COROUTINE\$${coroutineId++}".synthesizedName
override fun buildStateMachine(
originalBody: IrBody,
stateMachineFunction: IrFunction,

View File

@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
@@ -41,6 +42,7 @@ interface KotlinResolutionCallbacks {
receiverType: UnwrappedType?,
parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables
annotations: Annotations,
stubsForPostponedVariables: Map<NewTypeVariable, StubType>
): Pair<List<KotlinCallArgument>, InferenceSession?>

View File

@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.model.isIntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.model.typeConstructor
import org.jetbrains.kotlin.types.typeUtil.contains
class KotlinCallCompleter(
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
@@ -140,7 +141,7 @@ class KotlinCallCompleter(
private fun KotlinResolutionCandidate.returnTypeWithSmartCastInfo(resolutionCallbacks: KotlinResolutionCallbacks): UnwrappedType? {
val returnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return null
val returnTypeWithSmartCastInfo = computeReturnTypeWithSmartCastInfo(returnType, resolutionCallbacks)
return resolvedCall.substitutor.substituteKeepAnnotations(returnTypeWithSmartCastInfo)
return resolvedCall.substitutor.safeSubstitute(returnTypeWithSmartCastInfo)
}
private fun KotlinResolutionCandidate.addExpectedTypeConstraint(
@@ -197,10 +198,27 @@ class KotlinCallCompleter(
else
ConstraintSystemCompletionMode.PARTIAL
// Return type has proper equal constraints => there is no need in the outer call
containsTypeVariablesWithProperEqualConstraints(currentReturnType) -> ConstraintSystemCompletionMode.FULL
else -> ConstraintSystemCompletionMode.PARTIAL
}
}
private fun KotlinResolutionCandidate.containsTypeVariablesWithProperEqualConstraints(type: UnwrappedType): Boolean {
for ((variableConstructor, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) {
if (!type.contains { it.constructor == variableConstructor }) continue
val constraints = variableWithConstraints.constraints
val onlyProperEqualConstraints =
constraints.isNotEmpty() && constraints.all { it.kind.isEqual() && csBuilder.isProperType(it.type) }
if (!onlyProperEqualConstraints) return false
}
return true
}
private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean {
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
@@ -210,7 +228,8 @@ class KotlinCallCompleter(
val constraints = variableWithConstraints.constraints
return constraints.isNotEmpty() && constraints.all {
!it.type.typeConstructor(context).isIntegerLiteralTypeConstructor(context) &&
it.kind.isLower() && csBuilder.isProperType(it.type)
(it.kind.isLower() || it.kind.isEqual()) &&
csBuilder.isProperType(it.type)
}
}

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubsystemFromArgument
import org.jetbrains.kotlin.resolve.calls.inference.model.*
@@ -105,6 +106,7 @@ class PostponedArgumentsAnalyzer(
receiver,
parameters,
expectedTypeForReturnArguments,
lambda.expectedType?.annotations ?: Annotations.EMPTY,
stubsForPostponedVariables.cast()
)

View File

@@ -290,7 +290,7 @@ private fun KotlinResolutionCandidate.prepareExpectedType(
callComponents.languageVersionSettings
)
val resultType = knownTypeParametersResultingSubstitutor?.substitute(argumentType) ?: argumentType
return resolvedCall.substitutor.substituteKeepAnnotations(resultType)
return resolvedCall.substitutor.safeSubstitute(resultType)
}
private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion(

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
import org.jetbrains.kotlin.types.*
@@ -17,9 +18,7 @@ import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
interface NewTypeSubstitutor: TypeSubstitutorMarker {
fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType?
fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = false) ?: type
fun substituteKeepAnnotations(type: UnwrappedType): UnwrappedType =
fun safeSubstitute(type: UnwrappedType): UnwrappedType =
substitute(type, runCapturedChecks = true, keepAnnotation = true) ?: type
private fun substitute(type: UnwrappedType, keepAnnotation: Boolean, runCapturedChecks: Boolean): UnwrappedType? =
@@ -114,7 +113,7 @@ interface NewTypeSubstitutor: TypeSubstitutorMarker {
// simple classifier type
var replacement = substituteNotNullTypeWithConstructor(typeConstructor) ?: return null
if (keepAnnotation) {
replacement = replacement.replaceAnnotations(type.annotations)
replacement = replacement.replaceAnnotations(CompositeAnnotations(replacement.annotations, type.annotations))
}
if (type.isMarkedNullable) {
replacement = replacement.makeNullableAsSpecified(true)

View File

@@ -25,7 +25,7 @@ fun <T> bind2(r: Option<T>): Option<T> {
}
fun <T, R> bind3(r: Option<T>): Option<T> {
return <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (r is Some) {
return <!NI;TYPE_MISMATCH!>if (r is Some) {
// Diagnoses an error correctly
if (true) <!OI;TYPE_MISMATCH!>None<R>()<!> else r
}

View File

@@ -9,8 +9,8 @@ fun test() {
// KT-KT-9070
<!TYPE_MISMATCH!>{ }<!> <!USELESS_ELVIS!>?: 1<!>
use(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>{ 2 }<!> <!USELESS_ELVIS!>?: 1<!>);
use({ 2 } <!USELESS_ELVIS!>?: 1<!>);
1 <!USELESS_ELVIS!>?: <!TYPE_MISMATCH, UNUSED_LAMBDA_EXPRESSION!>{ }<!><!>
use(1 <!USELESS_ELVIS!>?: <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>{ }<!><!>)
use(1 <!USELESS_ELVIS!>?: { }<!>)
}

View File

@@ -19,8 +19,8 @@ fun test(i: Int?) {
foo(<!REDUNDANT_LABEL_WARNING!>l4@<!> <!TYPE_MISMATCH!>""<!>)
foo((<!TYPE_MISMATCH!>""<!>))
foo(checkSubtype<Int>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>""<!>))
foo(<!NI;TYPE_MISMATCH, TYPE_MISMATCH!>checkSubtype<Long>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>""<!>)<!>)
foo(checkSubtype<Int>(<!TYPE_MISMATCH!>""<!>))
foo(<!TYPE_MISMATCH!>checkSubtype<Long>(<!TYPE_MISMATCH!>""<!>)<!>)
use(a, b, c, d)
}

View File

@@ -18,9 +18,9 @@ class A<F> {
fun <Z : F, W : Z?> bar() {
// F
fooInv1<Inv<F>>(Inv<F>())
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<F><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<F>()<!>)
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<F><!>>(Inv<F>())
fooInv1(Inv<F>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<F>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH!>Inv<F>()<!>)
fooIn1<In<F?>>(In<F?>())
fooIn2<In<F?>>(In<F?>())
@@ -33,15 +33,15 @@ class A<F> {
fooOut2(Out<F>())
// Z
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(Inv<Z>())
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(Inv<Z>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH!>Inv<Z>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH!>Inv<Z>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
fooIn2<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<Z?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<Z?>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(In<Z?>())
fooIn2<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(In<Z?>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
fooOut1<Out<Z>>(Out<Z>())
fooOut2<Out<Z>>(Out<Z>())
@@ -49,19 +49,19 @@ class A<F> {
fooOut2(Out<Z>())
// W
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(Inv<W>())
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(Inv<W>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH!>Inv<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH!>Inv<W>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
fooIn2<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<W?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<W?>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(In<W?>())
fooIn2<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(In<W?>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
fooOut1<<!UPPER_BOUND_VIOLATED!>Out<W><!>>(<!NI;TYPE_MISMATCH!>Out<W>()<!>)
fooOut1<<!UPPER_BOUND_VIOLATED!>Out<W><!>>(Out<W>())
fooOut2<Out<W>>(Out<W>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooOut1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Out<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooOut1<!>(<!NI;TYPE_MISMATCH!>Out<W>()<!>)
fooOut2(Out<W>())
}
}

View File

@@ -13,14 +13,14 @@ class A<T> {
}
fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Out<CharSequence>()<!>)
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo1<!>(<!NI;TYPE_MISMATCH!>Out<CharSequence>()<!>)
a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(<!NI;TYPE_MISMATCH!><!NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER, NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>Out<!>()<!>)
a.foo1(<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>Out<!>())
a.foo1(Out<Nothing>())
a.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!NI;TYPE_MISMATCH!><!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>()<!>)
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH!>Inv()<!>)
a.foo3(In())
@@ -32,11 +32,11 @@ fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
b.foo1<Out<CharSequence>>(Out())
b.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!NI;TYPE_MISMATCH!><!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH!>Inv()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo3<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<CharSequence>()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo3<!>(<!NI;TYPE_MISMATCH!>In<CharSequence>()<!>)
b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(<!NI;TYPE_MISMATCH!>In()<!>)
b.foo3(In<Any?>())

View File

@@ -21,7 +21,7 @@ fun baz4(x: @MyDsl B.() -> Unit) {}
fun @MyDsl A.baz5() {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}
@@ -36,21 +36,21 @@ fun main() {
baz3 {
baz2 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}
baz1 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}
baz3 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}

View File

@@ -22,7 +22,7 @@ fun baz4(x: @MyDsl B.() -> Unit) {}
fun @MyDsl A.baz5() {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
@@ -37,21 +37,21 @@ fun main() {
baz3 {
baz2 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
baz1 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
baz3 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}

View File

@@ -0,0 +1,19 @@
@DslMarker
annotation class MyDsl
@MyDsl
interface Foo<T> {
val x: Int
}
val Foo<*>.bad: Int get() = x
fun Foo<*>.badFun(): Int = x
val Foo<Int>.good: Int get() = x
fun test(foo: Foo<*>) {
foo.apply {
x
}
}

View File

@@ -0,0 +1,20 @@
package
public val Foo<*>.bad: kotlin.Int
public val Foo<kotlin.Int>.good: kotlin.Int
public fun test(/*0*/ foo: Foo<*>): kotlin.Unit
public fun Foo<*>.badFun(): kotlin.Int
@MyDsl public interface Foo</*0*/ T> {
public abstract val x: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.DslMarker public final annotation class MyDsl : kotlin.Annotation {
public constructor MyDsl()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}

View File

@@ -0,0 +1,25 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class MyDsl
@MyDsl
interface Scope<A, B> {
val something: A
val value: B
}
fun scoped1(block: Scope<Int, String>.() -> Unit) {}
fun scoped2(block: Scope<*, String>.() -> Unit) {}
val <T> Scope<*, T>.property: T get() = value
fun f() {
scoped1 {
value
property
}
scoped2 {
value
property
}
}

View File

@@ -0,0 +1,21 @@
package
public val </*0*/ T> Scope<*, T>.property: T
public fun f(): kotlin.Unit
public fun scoped1(/*0*/ block: Scope<kotlin.Int, kotlin.String>.() -> kotlin.Unit): kotlin.Unit
public fun scoped2(/*0*/ block: Scope<*, kotlin.String>.() -> kotlin.Unit): kotlin.Unit
@kotlin.DslMarker public final annotation class MyDsl : kotlin.Annotation {
public constructor MyDsl()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@MyDsl public interface Scope</*0*/ A, /*1*/ B> {
public abstract val something: A
public abstract val value: B
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}

View File

@@ -0,0 +1,11 @@
@DslMarker
annotation class AnnMarker
@AnnMarker
class Inv<T> {
fun bar() {}
}
fun Inv<*>.foo() {
bar()
}

View File

@@ -0,0 +1,18 @@
package
public fun Inv<*>.foo(): kotlin.Unit
@kotlin.DslMarker public final annotation class AnnMarker : kotlin.Annotation {
public constructor AnnMarker()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@AnnMarker public final class Inv</*0*/ T> {
public constructor Inv</*0*/ T>()
public final fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}

View File

@@ -60,7 +60,7 @@ fun test() {
bar1t(this) {
a()
bar1 {
<!OI;DSL_SCOPE_VIOLATION!>a<!>()
<!DSL_SCOPE_VIOLATION!>a<!>()
b()
}
@@ -76,7 +76,7 @@ fun test() {
foo2 {
bar1t(this) {
a()
<!OI;DSL_SCOPE_VIOLATION!>b<!>()
<!DSL_SCOPE_VIOLATION!>b<!>()
}
}
}

View File

@@ -19,7 +19,7 @@ fun test() {
foo<A> {
a()
bar<B> {
<!OI;DSL_SCOPE_VIOLATION!>a<!>()
<!DSL_SCOPE_VIOLATION!>a<!>()
this@foo.a()
b()
}

View File

@@ -8,7 +8,7 @@ fun test() {
<!OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>
}<!>)
bar(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!><!OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> ?: <!OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!><!>)
bar(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!><!CONSTANT_EXPECTED_TYPE_MISMATCH, NI;CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> ?: <!CONSTANT_EXPECTED_TYPE_MISMATCH, NI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!><!>)
}
fun bar(s: String) = s

View File

@@ -0,0 +1,25 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
private object TopLevelTypeVariable {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> foo(): @kotlin.internal.NoInfer T = TODO()
fun <K> bar(k: K) {}
fun test() {
bar(foo<Int>())
}
}
private object NestedTypeVariable {
class Inv<T>
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> foo(): Inv<@kotlin.internal.NoInfer T> = TODO()
fun <K> bar(p: Inv<K>) {}
fun test() {
bar(foo<String>())
}
}

View File

@@ -0,0 +1,28 @@
package
private object NestedTypeVariable {
private constructor NestedTypeVariable()
public final fun </*0*/ K> bar(/*0*/ p: NestedTypeVariable.Inv<K>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public final fun </*0*/ T> foo(): NestedTypeVariable.Inv<T>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class Inv</*0*/ T> {
public constructor Inv</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
private object TopLevelTypeVariable {
private constructor TopLevelTypeVariable()
public final fun </*0*/ K> bar(/*0*/ k: K): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public final fun </*0*/ T> foo(): T
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}

View File

@@ -17482,6 +17482,21 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/insideTopLevelExtensionAnnotatedType.kt");
}
@TestMetadata("kt29948.kt")
public void testKt29948() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt29948.kt");
}
@TestMetadata("kt31360.kt")
public void testKt31360() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt31360.kt");
}
@TestMetadata("markedReceiverWithCapturedTypeArgument.kt")
public void testMarkedReceiverWithCapturedTypeArgument() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/markedReceiverWithCapturedTypeArgument.kt");
}
@TestMetadata("markersIntersection.kt")
public void testMarkersIntersection() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/markersIntersection.kt");

View File

@@ -2748,6 +2748,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/onlyInputTypesAnnotationWithPlatformTypes.kt");
}
@TestMetadata("propagationOfNoInferAnnotation.kt")
public void testPropagationOfNoInferAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/propagationOfNoInferAnnotation.kt");
}
@TestMetadata("resolveWithOnlyInputTypesAnnotation.kt")
public void testResolveWithOnlyInputTypesAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/resolveWithOnlyInputTypesAnnotation.kt");

View File

@@ -2748,6 +2748,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/onlyInputTypesAnnotationWithPlatformTypes.kt");
}
@TestMetadata("propagationOfNoInferAnnotation.kt")
public void testPropagationOfNoInferAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/propagationOfNoInferAnnotation.kt");
}
@TestMetadata("resolveWithOnlyInputTypesAnnotation.kt")
public void testResolveWithOnlyInputTypesAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/resolveWithOnlyInputTypesAnnotation.kt");

View File

@@ -17472,6 +17472,21 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/insideTopLevelExtensionAnnotatedType.kt");
}
@TestMetadata("kt29948.kt")
public void testKt29948() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt29948.kt");
}
@TestMetadata("kt31360.kt")
public void testKt31360() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt31360.kt");
}
@TestMetadata("markedReceiverWithCapturedTypeArgument.kt")
public void testMarkedReceiverWithCapturedTypeArgument() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/markedReceiverWithCapturedTypeArgument.kt");
}
@TestMetadata("markersIntersection.kt")
public void testMarkersIntersection() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/markersIntersection.kt");

View File

@@ -19,10 +19,11 @@
package org.jetbrains.kotlin.idea.imports
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -30,6 +31,7 @@ import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
object ImportPathComparator : Comparator<ImportPath> {
@@ -94,5 +96,8 @@ fun KtReferenceExpression.getImportableTargets(bindingContext: BindingContext):
return targets.map { it.getImportableDescriptor() }.toSet()
}
fun KtImportDirective.canResolve(): Boolean = (importedReference?.getQualifiedElementSelector() as? KtNameReferenceExpression)
?.reference?.resolve() != null ?: false
fun KtImportDirective.canResolve(facade: ResolutionFacade): Boolean {
return (importedReference?.getQualifiedElementSelector() as? KtSimpleNameExpression)?.let { nameExpression ->
nameExpression.getImportableTargets(facade.analyze(nameExpression, BodyResolveMode.PARTIAL)).isNotEmpty()
} ?: false
}

View File

@@ -60,7 +60,8 @@ class OptimizedImportsBuilder(
}
data class InputData(
val descriptorsToImport: Map<DeclarationDescriptor, Set<Name>>,
val descriptorsToImport: Set<DeclarationDescriptor>,
val namesToImport: Map<FqName, Set<Name>>,
val references: Collection<AbstractReference>
)
@@ -87,8 +88,9 @@ class OptimizedImportsBuilder(
private val importRules = HashSet<ImportRule>()
fun buildOptimizedImports(): List<ImportPath>? {
val facade = file.getResolutionFacade()
file.importDirectives
.filterNot(KtImportDirective::canResolve)
.filterNot { it.canResolve(facade) }
.mapNotNull(KtImportDirective::getImportPath)
.mapTo(importRules) { ImportRule.Add(it) }
@@ -118,9 +120,9 @@ class OptimizedImportsBuilder(
.mapTo(importsToGenerate) { it.importPath }
val descriptorsByParentFqName = HashMap<FqName, MutableSet<DeclarationDescriptor>>()
for ((descriptor, names) in data.descriptorsToImport) {
for (name in names) {
val fqName = descriptor.importableFqName!!
for (descriptor in data.descriptorsToImport) {
val fqName = descriptor.importableFqName!!
for (name in data.namesToImport.getValue(fqName)) {
val alias = if (name != fqName.shortName()) name else null
val explicitImportPath = ImportPath(fqName, false, alias)
@@ -148,16 +150,16 @@ class OptimizedImportsBuilder(
|| !starImportPath.isAllowedByRules()
if (useExplicitImports) {
fqNames
.filter { !isImportedByDefault(it) }
.filter(this::needExplicitImport)
.mapTo(importsToGenerate) { ImportPath(it, false) }
} else {
descriptors
.asSequence()
.filterIsInstance<ClassDescriptor>()
.map { it.importableFqName!! }
.filterTo(classNamesToCheck) { !isImportedByDefault(it) }
.filterTo(classNamesToCheck, this::needExplicitImport)
if (!fqNames.all(this::isImportedByDefault)) {
if (fqNames.all(this::needExplicitImport)) {
importsToGenerate.add(starImportPath)
}
}
@@ -204,7 +206,7 @@ class OptimizedImportsBuilder(
(oldTargets + newTargets).forEach {
lockImportForDescriptor(
it,
data.descriptorsToImport.getOrElse(it) { listOf(it.name) }.intersect(names)
data.namesToImport.getOrElse(it.importableFqName!!) { listOf(it.name) }.intersect(names)
)
}
}
@@ -320,6 +322,12 @@ class OptimizedImportsBuilder(
}
}
private fun needExplicitImport(fqName: FqName): Boolean = hasAlias(fqName) || !isImportedByDefault(fqName)
private fun hasAlias(fqName: FqName) = data.namesToImport[fqName]?.let {
it.singleOrNull() == null
} ?: false
private fun isImportedByDefault(fqName: FqName) = importInsertHelper.isImportedWithDefault(ImportPath(fqName, false), file)
private fun isImportedByLowPriorityDefault(fqName: FqName) =

View File

@@ -85,7 +85,7 @@ object SourceNavigationHelper {
private fun Collection<GlobalSearchScope>.union(): List<GlobalSearchScope> =
if (this.isNotEmpty()) listOf(GlobalSearchScope.union(this.toTypedArray())) else emptyList()
private fun haveRenamesInImports(files: Collection<KtFile>) = files.any { it.importDirectives.any { it.aliasName != null } }
private fun haveRenamesInImports(files: Collection<KtFile>) = files.any { file -> file.importDirectives.any { it.aliasName != null } }
private fun findSpecialProperty(memberName: Name, containingClass: KtClass): KtNamedDeclaration? {
// property constructor parameters
@@ -191,7 +191,7 @@ object SourceNavigationHelper {
): T? {
val classFqName = entity.fqName ?: return null
return targetScopes(entity, navigationKind).firstNotNullResult { scope ->
index.get(classFqName.asString(), entity.project, scope).sortedBy { it.isExpectDeclaration() }.firstOrNull()
index.get(classFqName.asString(), entity.project, scope).minBy { it.isExpectDeclaration() }
}
}
@@ -273,7 +273,15 @@ object SourceNavigationHelper {
SourceNavigationHelper.NavigationKind.SOURCES_TO_CLASS_FILES -> {
val file = from.containingFile
if (file is KtFile && file.isCompiled) return from
if (!ProjectRootsUtil.isInContent(from, false, true, false, true, false)) return from
if (!ProjectRootsUtil.isInContent(
from,
includeProjectSource = false,
includeLibrarySource = true,
includeLibraryClasses = false,
includeScriptDependencies = true,
includeScriptsOutsideSourceRoots = false
)
) return from
if (KtPsiUtil.isLocal(from)) return from
}
}

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.highlighter
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.idea.caches.project.NotUnderContentRootModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
@@ -36,12 +37,14 @@ object KotlinHighlightingUtil {
return true
}
if (ktFile.isScript()) {
return shouldHighlightScript(ktFile)
if (OutsidersPsiFileSupportWrapper.isOutsiderFile(ktFile.virtualFile)) {
val origin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(ktFile.project, ktFile.virtualFile) ?: return false
val psiFileOrigin = PsiManager.getInstance(ktFile.project).findFile(origin) ?: return false
return shouldHighlight(psiFileOrigin)
}
if (OutsidersPsiFileSupportWrapper.isOutsiderFile(ktFile.virtualFile)) {
return true
if (ktFile.isScript()) {
return shouldHighlightScript(ktFile)
}
return ProjectRootsUtil.isInProjectOrLibraryContent(ktFile) && ktFile.getModuleInfo() !is NotUnderContentRootModuleInfo

View File

@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.highlighter
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import java.io.File
import java.nio.file.Paths
object OutsidersPsiFileSupportUtils {
fun getOutsiderFileOrigin(project: Project, virtualFile: VirtualFile): VirtualFile? {
@@ -16,9 +16,8 @@ object OutsidersPsiFileSupportUtils {
val originalFilePath = OutsidersPsiFileSupportWrapper.getOriginalFilePath(virtualFile) ?: return null
return generateSequence(File(originalFilePath)) { if (it.canonicalPath == project.baseDir.canonicalPath) null else it.parentFile }
.filter { it.exists() }
.firstOrNull()
?.let { VfsUtil.findFileByIoFile(it, false) }
return generateSequence(VfsUtil.findFile(Paths.get(originalFilePath), true)) {
if (it == project.baseDir) null else it.parent
}.filter { it.exists() }.firstOrNull()
}
}

View File

@@ -38,8 +38,10 @@ import com.intellij.psi.PsiFile
import com.intellij.util.ui.UIUtil
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.ScriptDependenciesUpdater
import org.jetbrains.kotlin.psi.KtFile
import kotlin.script.experimental.dependencies.ScriptDependencies
import kotlin.script.experimental.dependencies.ScriptReport
class ScriptExternalHighlightingPass(
@@ -60,12 +62,14 @@ class ScriptExternalHighlightingPass(
)
}
// show notification only for async resolvers, for others file analysis is in progress until all dependencies are ready
if (!ScriptDependenciesUpdater.areDependenciesCached(file) && ScriptDependenciesUpdater.isAsyncDependencyResolver(file)) {
showNotification(
file,
"Highlighting in scripts is not available until all Script Dependencies are loaded"
)
if (!ScriptDependenciesUpdater.areDependenciesCached(file)) {
val scriptDependencies = ScriptDependenciesManager.getInstance(file.project).getScriptDependencies(file.virtualFile)
if (scriptDependencies == ScriptDependencies.Empty) {
showNotification(
file,
"Highlighting in scripts is not available until all Script Dependencies are loaded"
)
}
}
val reports = file.virtualFile.getUserData(IdeScriptReportSink.Reports) ?: return

View File

@@ -37,9 +37,9 @@ class KtPropertyDelegationMethodsReference(element: KtPropertyDelegate) : KtMult
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val property = expression.getStrictParentOfType<KtProperty>() ?: return emptyList()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptorWithAccessors ?: return emptyList()
return (descriptor.accessors.mapNotNull {
accessor ->
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptorWithAccessors
?: return emptyList()
return (descriptor.accessors.mapNotNull { accessor ->
context.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor)?.candidateDescriptor
} + listOfNotNull(context.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor)?.candidateDescriptor))
}
@@ -47,6 +47,10 @@ class KtPropertyDelegationMethodsReference(element: KtPropertyDelegate) : KtMult
override val resolvesByNames: Collection<Name> get() = NAMES
companion object {
private val NAMES = listOf(OperatorNameConventions.GET_VALUE, OperatorNameConventions.SET_VALUE)
private val NAMES = listOf(
OperatorNameConventions.GET_VALUE,
OperatorNameConventions.SET_VALUE,
OperatorNameConventions.PROVIDE_DELEGATE
)
}
}

View File

@@ -85,50 +85,109 @@ class KotlinSourceFilterScope private constructor(
companion object {
@JvmStatic
fun sourcesAndLibraries(delegate: GlobalSearchScope, project: Project) = create(delegate, true, true, true, true, true, project)
fun sourcesAndLibraries(delegate: GlobalSearchScope, project: Project) = create(
delegate,
includeProjectSourceFiles = true,
includeLibrarySourceFiles = true,
includeClassFiles = true,
includeScriptDependencies = true,
includeScriptsOutsideSourceRoots = true,
project = project
)
@JvmStatic
fun sourceAndClassFiles(delegate: GlobalSearchScope, project: Project) = create(delegate, true, false, true, true, true, project)
fun sourceAndClassFiles(delegate: GlobalSearchScope, project: Project) = create(
delegate,
includeProjectSourceFiles = true,
includeLibrarySourceFiles = false,
includeClassFiles = true,
includeScriptDependencies = true,
includeScriptsOutsideSourceRoots = true,
project = project
)
@JvmStatic
fun projectSourceAndClassFiles(delegate: GlobalSearchScope, project: Project) = create(delegate, true, false, true, false, true, project)
fun projectSourceAndClassFiles(delegate: GlobalSearchScope, project: Project) = create(
delegate,
includeProjectSourceFiles = true,
includeLibrarySourceFiles = false,
includeClassFiles = true,
includeScriptDependencies = false,
includeScriptsOutsideSourceRoots = true,
project = project
)
@JvmStatic
fun projectSources(delegate: GlobalSearchScope, project: Project) = create(delegate, true, false, false, false, true, project)
fun projectSources(delegate: GlobalSearchScope, project: Project) = create(
delegate,
includeProjectSourceFiles = true,
includeLibrarySourceFiles = false,
includeClassFiles = false,
includeScriptDependencies = false,
includeScriptsOutsideSourceRoots = true,
project = project
)
@JvmStatic
fun librarySources(delegate: GlobalSearchScope, project: Project) = create(delegate, false, true, false, true, false, project)
fun librarySources(delegate: GlobalSearchScope, project: Project) = create(
delegate,
includeProjectSourceFiles = false,
includeLibrarySourceFiles = true,
includeClassFiles = false,
includeScriptDependencies = true,
includeScriptsOutsideSourceRoots = false,
project = project
)
@JvmStatic
fun libraryClassFiles(delegate: GlobalSearchScope, project: Project) = create(delegate, false, false, true, true, false, project)
fun libraryClassFiles(delegate: GlobalSearchScope, project: Project) = create(
delegate,
includeProjectSourceFiles = false,
includeLibrarySourceFiles = false,
includeClassFiles = true,
includeScriptDependencies = true,
includeScriptsOutsideSourceRoots = false,
project = project
)
@JvmStatic
fun projectAndLibrariesSources(delegate: GlobalSearchScope, project: Project) = create(delegate, true, true, false, false, true, project)
fun projectAndLibrariesSources(delegate: GlobalSearchScope, project: Project) = create(
delegate,
includeProjectSourceFiles = true,
includeLibrarySourceFiles = true,
includeClassFiles = false,
includeScriptDependencies = false,
includeScriptsOutsideSourceRoots = true,
project = project
)
private fun create(
delegate: GlobalSearchScope,
includeProjectSourceFiles: Boolean,
includeLibrarySourceFiles: Boolean,
includeClassFiles: Boolean,
includeScriptDependencies: Boolean,
includeScriptsOutsideSourceRoots: Boolean,
project: Project
delegate: GlobalSearchScope,
includeProjectSourceFiles: Boolean,
includeLibrarySourceFiles: Boolean,
includeClassFiles: Boolean,
includeScriptDependencies: Boolean,
includeScriptsOutsideSourceRoots: Boolean,
project: Project
): GlobalSearchScope {
if (delegate === GlobalSearchScope.EMPTY_SCOPE) return delegate
if (delegate is KotlinSourceFilterScope) {
return KotlinSourceFilterScope(
delegate.myBaseScope,
includeProjectSourceFiles = delegate.includeProjectSourceFiles && includeProjectSourceFiles,
includeLibrarySourceFiles = delegate.includeLibrarySourceFiles && includeLibrarySourceFiles,
includeClassFiles = delegate.includeClassFiles && includeClassFiles,
includeScriptDependencies = delegate.includeScriptDependencies && includeScriptDependencies,
includeScriptsOutsideSourceRoots = delegate.includeScriptsOutsideSourceRoots && includeScriptsOutsideSourceRoots,
project = project
delegate.myBaseScope,
includeProjectSourceFiles = delegate.includeProjectSourceFiles && includeProjectSourceFiles,
includeLibrarySourceFiles = delegate.includeLibrarySourceFiles && includeLibrarySourceFiles,
includeClassFiles = delegate.includeClassFiles && includeClassFiles,
includeScriptDependencies = delegate.includeScriptDependencies && includeScriptDependencies,
includeScriptsOutsideSourceRoots = delegate.includeScriptsOutsideSourceRoots && includeScriptsOutsideSourceRoots,
project = project
)
}
return KotlinSourceFilterScope(delegate, includeProjectSourceFiles, includeLibrarySourceFiles, includeClassFiles, includeScriptDependencies, includeScriptsOutsideSourceRoots, project)
return KotlinSourceFilterScope(
delegate, includeProjectSourceFiles, includeLibrarySourceFiles, includeClassFiles,
includeScriptDependencies, includeScriptsOutsideSourceRoots, project
)
}
}
}

View File

@@ -354,12 +354,10 @@ fun KtDeclaration.isOverridable(): Boolean {
}
}
fun KtDeclaration.getModalityFromDescriptor(): KtModifierKeywordToken? {
val descriptor = this.resolveToDescriptorIfAny()
fun KtDeclaration.getModalityFromDescriptor(descriptor: DeclarationDescriptor? = resolveToDescriptorIfAny()): KtModifierKeywordToken? {
if (descriptor is MemberDescriptor) {
return mapModality(descriptor.modality)
}
return null
}

View File

@@ -78,12 +78,12 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
if (nonScriptFileName(fileName)) return null
if (!isReady()) return null
val cached = synchronized(scriptDefinitionsCacheLock) { scriptDefinitionsCache.get(fileName) }
val cached = scriptDefinitionsCacheLock.write { scriptDefinitionsCache.get(fileName) }
if (cached != null) return cached
val definition = super.findScriptDefinition(fileName) ?: return null
synchronized(scriptDefinitionsCacheLock) {
scriptDefinitionsCacheLock.write {
scriptDefinitionsCache.put(fileName, definition)
}
@@ -184,7 +184,7 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
}
clearCache()
scriptDefinitionsCache.clear()
scriptDefinitionsCacheLock.write { scriptDefinitionsCache.clear() }
// TODO: clear by script type/definition
ServiceManager.getService(project, ScriptDependenciesCache::class.java).clear()

View File

@@ -76,9 +76,8 @@ class ScriptDependenciesManager internal constructor(
@TestOnly
fun updateScriptDependenciesSynchronously(virtualFile: VirtualFile, project: Project) {
val scriptDefinition = virtualFile.findScriptDefinition(project)!!
val loader = SyncScriptDependenciesLoader(project)
loader.updateDependencies(virtualFile, scriptDefinition)
loader.updateDependencies(virtualFile)
loader.notifyRootsChanged()
}
}

View File

@@ -35,13 +35,13 @@ 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
import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependenciesLoader
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.scriptDefinition
import org.jetbrains.kotlin.scripting.resolve.LegacyResolverWrapper
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
import kotlin.script.experimental.dependencies.ScriptDependencies
@@ -53,9 +53,12 @@ class ScriptDependenciesUpdater(
private val scriptsQueue = Alarm(Alarm.ThreadToUse.SWING_THREAD, project)
private val scriptChangesListenerDelay = 1400
private val asyncLoader = AsyncScriptDependenciesLoader(project)
private val syncLoader = SyncScriptDependenciesLoader(project)
private val fileAttributeLoader = FromFileAttributeScriptDependenciesLoader(project)
private val loaders = arrayListOf(
FromFileAttributeScriptDependenciesLoader(project),
OutsiderFileDependenciesLoader(project),
AsyncScriptDependenciesLoader(project),
SyncScriptDependenciesLoader(project)
)
init {
listenForChangesInScripts()
@@ -64,45 +67,38 @@ class ScriptDependenciesUpdater(
fun getCurrentDependencies(file: VirtualFile): ScriptDependencies {
cache[file]?.let { return it }
val scriptDef = file.findScriptDefinition(project) ?: return ScriptDependencies.Empty
fileAttributeLoader.updateDependencies(file, scriptDef)
updateDependencies(file, scriptDef)
updateDependencies(file)
makeRootsChangeIfNeeded()
return cache[file] ?: ScriptDependencies.Empty
}
fun updateDependenciesIfNeeded(files: List<VirtualFile>): Boolean {
val definitionsManager = ScriptDefinitionsManager.getInstance(project)
if (definitionsManager.isReady() && areDependenciesCached(files)) {
return false
}
if (!ScriptDefinitionsManager.getInstance(project).isReady()) return false
var wasDependenciesUpdateStarted = false
for (file in files) {
val scriptDef = file.findScriptDefinition(project) ?: continue
updateDependencies(file, scriptDef)
if (!areDependenciesCached(file)) {
wasDependenciesUpdateStarted = true
updateDependencies(file)
}
}
makeRootsChangeIfNeeded()
if (wasDependenciesUpdateStarted) {
makeRootsChangeIfNeeded()
}
return true
return wasDependenciesUpdateStarted
}
private fun updateDependencies(file: VirtualFile, scriptDef: KotlinScriptDefinition) {
val loader = when {
isAsyncDependencyResolver(scriptDef) -> asyncLoader
else -> syncLoader
}
loader.updateDependencies(file, scriptDef)
private fun updateDependencies(file: VirtualFile) {
loaders.filter { it.isApplicable(file) }.forEach { it.updateDependencies(file) }
}
private fun makeRootsChangeIfNeeded() {
if (fileAttributeLoader.notifyRootsChanged()) return
if (syncLoader.notifyRootsChanged()) return
if (asyncLoader.notifyRootsChanged()) return
loaders.firstOrNull {
it.notifyRootsChanged()
}
}
private fun listenForChangesInScripts() {
@@ -116,24 +112,15 @@ class ScriptDependenciesUpdater(
}
private fun runScriptDependenciesUpdateIfNeeded(file: VirtualFile) {
if (file.fileType != KotlinFileType.INSTANCE || !file.isValid) return
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return
if (!shouldStartUpdate(file)) return
if (ApplicationManager.getApplication().isUnitTestMode && ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled == true) return
val scriptDef = ktFile.scriptDefinition() ?: return
if (!ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)) return
updateDependencies(file, scriptDef)
updateDependencies(file)
makeRootsChangeIfNeeded()
}
})
EditorFactory.getInstance().eventMulticaster.addDocumentListener(object : DocumentListener {
override fun documentChanged(event: DocumentEvent) {
if (project.isDisposed) return
if (ApplicationManager.getApplication().isUnitTestMode && ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled == true) return
val document = event.document
val file = FileDocumentManager.getInstance().getFile(document)?.takeIf { it.isInLocalFileSystem } ?: return
@@ -142,22 +129,20 @@ class ScriptDependenciesUpdater(
return
}
if (!shouldStartUpdate(file)) return
// only update dependencies for scripts that were touched recently
if (cache[file] == null) {
return
}
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return
val scriptDef = ktFile.scriptDefinition() ?: return
if (!ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)) return
scriptsQueue.cancelAllRequests()
scriptsQueue.addRequest(
{
FileDocumentManager.getInstance().saveDocument(document)
updateDependencies(file, scriptDef)
updateDependencies(file)
makeRootsChangeIfNeeded()
},
scriptChangesListenerDelay,
true
@@ -166,15 +151,27 @@ class ScriptDependenciesUpdater(
}, project.messageBus.connect())
}
private fun shouldStartUpdate(file: VirtualFile): Boolean {
if (project.isDisposed || !file.isValid || file.fileType != KotlinFileType.INSTANCE) {
return false
}
if (
ApplicationManager.getApplication().isUnitTestMode &&
ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled == true
) {
return false
}
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return false
return ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)
}
private fun areDependenciesCached(file: VirtualFile): Boolean {
return cache[file] != null || file.scriptDependencies != null
}
private fun areDependenciesCached(files: List<VirtualFile>): Boolean {
return files.all { areDependenciesCached(it) }
}
private fun isAsyncDependencyResolver(scriptDef: KotlinScriptDefinition): Boolean {
fun isAsyncDependencyResolver(scriptDef: KotlinScriptDefinition): Boolean {
val dependencyResolver = scriptDef.dependencyResolver
return dependencyResolver is AsyncDependenciesResolver || dependencyResolver is LegacyResolverWrapper
}

View File

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

View File

@@ -8,22 +8,16 @@ 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.scriptDependencies
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
import kotlin.script.experimental.dependencies.ScriptDependencies
class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
override fun loadDependencies(file: VirtualFile, scriptDef: KotlinScriptDefinition) {
val deserializedDependencies = file.scriptDependencies ?: return
saveToCache(deserializedDependencies, file)
override fun isApplicable(file: VirtualFile): Boolean {
return file.scriptDependencies != null
}
private fun saveToCache(deserialized: ScriptDependencies, file: VirtualFile) {
val rootsChanged = cache.hasNotCachedRoots(deserialized)
cache.save(file, deserialized)
if (rootsChanged) {
shouldNotifyRootsChanged = true
}
override fun loadDependencies(file: VirtualFile) {
val deserializedDependencies = file.scriptDependencies ?: return
saveToCache(file, deserializedDependencies)
}
override fun shouldShowNotification(): Boolean = false

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.core.script.dependencies
import com.intellij.openapi.project.Project
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
class OutsiderFileDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
override fun isApplicable(file: VirtualFile): Boolean {
return OutsidersPsiFileSupportWrapper.isOutsiderFile(file)
}
override fun loadDependencies(file: VirtualFile) {
val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, file) ?: return
saveToCache(file, ScriptDependenciesManager.getInstance(project).getScriptDependencies(fileOrigin))
}
override fun shouldShowNotification(): Boolean = false
}

View File

@@ -21,20 +21,23 @@ import org.jetbrains.kotlin.scripting.resolve.ScriptContentLoader
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.dependencies.ScriptDependencies
abstract class ScriptDependenciesLoader(protected val project: Project) {
fun updateDependencies(file: VirtualFile, scriptDef: KotlinScriptDefinition) {
fun updateDependencies(file: VirtualFile) {
if (fileModificationStamps[file.path] != file.modificationStamp) {
fileModificationStamps.put(file.path, file.modificationStamp)
loadDependencies(file, scriptDef)
loadDependencies(file)
}
}
private val fileModificationStamps: SLRUMap<String, Long> = SLRUMap(MAX_SCRIPTS_CACHED, MAX_SCRIPTS_CACHED)
protected abstract fun loadDependencies(file: VirtualFile, scriptDef: KotlinScriptDefinition)
abstract fun isApplicable(file: VirtualFile): Boolean
protected abstract fun loadDependencies(file: VirtualFile)
protected abstract fun shouldShowNotification(): Boolean
protected var shouldNotifyRootsChanged = false
@@ -84,6 +87,10 @@ abstract class ScriptDependenciesLoader(protected val project: Project) {
}
val dependencies = result.dependencies?.adjustByDefinition(scriptDef) ?: return
saveToCache(file, dependencies)
}
protected fun saveToCache(file: VirtualFile, dependencies: ScriptDependencies) {
val rootsChanged = cache.hasNotCachedRoots(dependencies)
if (cache.save(file, dependencies)) {
file.scriptDependencies = dependencies

View File

@@ -7,10 +7,17 @@ package org.jetbrains.kotlin.idea.core.script.dependencies
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
class SyncScriptDependenciesLoader internal constructor(project: Project) : ScriptDependenciesLoader(project) {
override fun loadDependencies(file: VirtualFile, scriptDef: KotlinScriptDefinition) {
override fun isApplicable(file: VirtualFile): Boolean {
val scriptDefinition = file.findScriptDefinition(project) ?: return false
return !ScriptDependenciesUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
}
override fun loadDependencies(file: VirtualFile) {
val scriptDef = file.findScriptDefinition(project) ?: return
val result = contentLoader.loadContentsAndResolveDependencies(scriptDef, file)
processResult(result, file, scriptDef)
}

View File

@@ -87,8 +87,7 @@ class GroovyBuildScriptManipulator(
}
}
}
}
else {
} else {
val applyPluginDirective = getGroovyApplyPluginDirective(kotlinPluginName)
if (!containsDirective(scriptFile.text, applyPluginDirective)) {
val apply = GroovyPsiElementFactory.getInstance(scriptFile.project).createExpressionFromText(applyPluginDirective)
@@ -246,11 +245,11 @@ class GroovyBuildScriptManipulator(
.getBlockOrCreate("resolutionStrategy")
.getBlockOrCreate("eachPlugin")
.addLastStatementInBlockIfNeeded(
"""
if (requested.id.id == "$pluginId") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${'$'}{requested.version}")
}
""".trimIndent()
"""
if (requested.id.id == "$pluginId") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${'$'}{requested.version}")
}
""".trimIndent()
)
}
@@ -415,9 +414,9 @@ class GroovyBuildScriptManipulator(
}
companion object {
private val VERSION_TEMPLATE = "\$VERSION$"
private const val VERSION_TEMPLATE = "\$VERSION$"
private val VERSION = String.format("ext.kotlin_version = '%s'", VERSION_TEMPLATE)
private val GRADLE_PLUGIN_ID = "kotlin-gradle-plugin"
private const val GRADLE_PLUGIN_ID = "kotlin-gradle-plugin"
private val CLASSPATH = "classpath \"$KOTLIN_GROUP_ID:$GRADLE_PLUGIN_ID:\$kotlin_version\""
private fun PsiElement.getBlockByName(name: String): GrClosableBlock? {
@@ -454,13 +453,13 @@ class GroovyBuildScriptManipulator(
}
fun GrClosableBlock.addLastExpressionInBlockIfNeeded(expressionText: String): Boolean =
addExpressionOrStatementInBlockIfNeeded(expressionText, false, false)
addExpressionOrStatementInBlockIfNeeded(expressionText, isStatement = false, isFirst = false)
fun GrClosableBlock.addLastStatementInBlockIfNeeded(expressionText: String): Boolean =
addExpressionOrStatementInBlockIfNeeded(expressionText, true, false)
addExpressionOrStatementInBlockIfNeeded(expressionText, isStatement = true, isFirst = false)
private fun GrClosableBlock.addFirstExpressionInBlockIfNeeded(expressionText: String): Boolean =
addExpressionOrStatementInBlockIfNeeded(expressionText, false, true)
addExpressionOrStatementInBlockIfNeeded(expressionText, isStatement = false, isFirst = true)
private fun GrClosableBlock.addExpressionOrStatementInBlockIfNeeded(text: String, isStatement: Boolean, isFirst: Boolean): Boolean {
if (statements.any { StringUtil.equalsIgnoreWhitespaces(it.text, text) }) return false

View File

@@ -56,7 +56,9 @@ class CodeFragmentCompiler(private val executionContext: ExecutionContext) {
return runReadAction { doCompile(codeFragment, bindingContext, moduleDescriptor) }
}
private fun doCompile(codeFragment: KtCodeFragment, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor): CompilationResult {
private fun doCompile(
codeFragment: KtCodeFragment, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor
): CompilationResult {
require(codeFragment is KtBlockCodeFragment || codeFragment is KtExpressionCodeFragment) {
"Unsupported code fragment type: $codeFragment"
}
@@ -111,7 +113,7 @@ class CodeFragmentCompiler(private val executionContext: ExecutionContext) {
}
val ownerClassName = typeMapper.mapOwner(parameter.targetDescriptor).internalName
val lastDollarIndex = ownerClassName.lastIndexOf('$').takeIf { it >= 0} ?: continue
val lastDollarIndex = ownerClassName.lastIndexOf('$').takeIf { it >= 0 } ?: continue
result[parameter.dumb] = ownerClassName.drop(lastDollarIndex)
}
@@ -176,7 +178,12 @@ class CodeFragmentCompiler(private val executionContext: ExecutionContext) {
val parameters = parameterInfo.parameters.mapIndexed { index, parameter ->
ValueParameterDescriptorImpl(
methodDescriptor, null, index, Annotations.EMPTY, Name.identifier("p$index"),
parameter.targetType, false, false, false, null, SourceElement.NO_SOURCE
parameter.targetType,
declaresDefaultValue = false,
isCrossinline = false,
isNoinline = false,
varargElementType = null,
source = SourceElement.NO_SOURCE
)
}

View File

@@ -37,11 +37,11 @@ import kotlin.reflect.KClass
// TODO: need to manage resources here, i.e. call replCompiler.dispose when engine is collected
class KotlinJsr223JvmScriptEngine4Idea(
factory: ScriptEngineFactory,
templateClasspath: List<File>,
templateClassName: String,
private val getScriptArgs: (ScriptContext, Array<out KClass<out Any>>?) -> ScriptArgsWithTypes?,
private val scriptArgsTypes: Array<out KClass<out Any>>?
factory: ScriptEngineFactory,
templateClasspath: List<File>,
templateClassName: String,
private val getScriptArgs: (ScriptContext, Array<out KClass<out Any>>?) -> ScriptArgsWithTypes?,
private val scriptArgsTypes: Array<out KClass<out Any>>?
) : KotlinJsr223JvmScriptEngineBase(factory) {
private val daemon by lazy {
@@ -53,28 +53,37 @@ class KotlinJsr223JvmScriptEngine4Idea(
val daemonReportMessages = arrayListOf<DaemonReportMessage>()
KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true)
?: throw ScriptException("Unable to connect to repl server:" + daemonReportMessages.joinToString("\n ", prefix = "\n ") { "${it.category.name} ${it.message}" })
KotlinCompilerClient.connectToCompileService(
compilerId, daemonJVMOptions, daemonOptions,
DaemonReportingTargets(null, daemonReportMessages),
autostart = true, checkId = true
) ?: throw ScriptException(
"Unable to connect to repl server:" + daemonReportMessages.joinToString("\n ", prefix = "\n ") {
"${it.category.name} ${it.message}"
}
)
}
private val messageCollector = MyMessageCollector()
override val replCompiler: ReplCompiler by lazy {
daemon.let {
KotlinRemoteReplCompilerClient(it,
makeAutodeletingFlagFile("idea-jsr223-repl-session"),
CompileService.TargetPlatform.JVM,
emptyArray(),
messageCollector,
templateClasspath,
templateClassName)
}
KotlinRemoteReplCompilerClient(
daemon,
makeAutodeletingFlagFile("idea-jsr223-repl-session"),
CompileService.TargetPlatform.JVM,
emptyArray(),
messageCollector,
templateClasspath,
templateClassName
)
}
override fun overrideScriptArgs(context: ScriptContext): ScriptArgsWithTypes? =
getScriptArgs(getContext(), scriptArgsTypes)
getScriptArgs(getContext(), scriptArgsTypes)
private val localEvaluator: ReplFullEvaluator by lazy { GenericReplCompilingEvaluator(replCompiler, templateClasspath, Thread.currentThread().contextClassLoader) }
private val localEvaluator: ReplFullEvaluator by lazy {
GenericReplCompilingEvaluator(replCompiler, templateClasspath, Thread.currentThread().contextClassLoader)
}
override val replEvaluator: ReplFullEvaluator get() = localEvaluator

View File

@@ -1263,6 +1263,11 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.AddNamesToFollowingArgumentsIntention</className>
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.ReplaceUnderscoreWithParameterNameIntention</className>
<category>Kotlin</category>
@@ -2365,6 +2370,15 @@
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ConvertNaNEqualityInspection"
displayName="Convert equality check with 'NaN' to 'isNaN' call"
groupPath="Kotlin"
groupName="Probable bugs"
enabledByDefault="true"
level="WARNING"
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.UnusedEqualsInspection"
displayName="Unused equals expression"
groupPath="Kotlin"

View File

@@ -0,0 +1,7 @@
<html>
<body>
This inspection reports an equality check with <b>Double.NaN</b> which can be replaced with <b>a.isNaN()</b>.
For every floating point value <b>a</b>, <b>a == NaN</b> will always result in <b>false</b>.
</body>
</html>

View File

@@ -0,0 +1,7 @@
fun foo(x: Int, y: Int, comment: String) {
}
fun test() {
foo(24, <spot>y = 42, comment = "Hello"</spot>)
}

View File

@@ -0,0 +1,7 @@
fun foo(x: Int, y: Int, comment: String) {
}
fun test() {
foo(24, <spot>42, "Hello"</spot>)
}

View File

@@ -0,0 +1,6 @@
<html>
<body>
This intention adds names to all positional arguments of a function call according to the named argument syntax,
starting with the current argument.
</body>
</html>

View File

@@ -79,11 +79,12 @@ class KotlinImportOptimizer : ImportOptimizer {
.mapNotNull { it.importPath }
.groupBy(keySelector = { it.fqName }, valueTransform = { it.importedName as Name })
private val descriptorsToImport = LinkedHashMap<DeclarationDescriptor, HashSet<Name>>()
private val descriptorsToImport = LinkedHashSet<DeclarationDescriptor>()
private val namesToImport = LinkedHashMap<FqName, HashSet<Name>>()
private val abstractRefs = ArrayList<OptimizedImportsBuilder.AbstractReference>()
val data: OptimizedImportsBuilder.InputData
get() = OptimizedImportsBuilder.InputData(descriptorsToImport, abstractRefs)
get() = OptimizedImportsBuilder.InputData(descriptorsToImport, namesToImport, abstractRefs)
override fun visitElement(element: PsiElement) {
ProgressIndicatorProvider.checkCanceled()
@@ -119,7 +120,8 @@ class KotlinImportOptimizer : ImportOptimizer {
if (isAccessibleAsMember(importableDescriptor, element, bindingContext)) continue
val descriptorNames = (aliases[importableFqName].orEmpty() + importableFqName.shortName()).intersect(names)
descriptorsToImport.getOrPut(importableDescriptor) { LinkedHashSet() } += descriptorNames
namesToImport.getOrPut(importableFqName) { LinkedHashSet() } += descriptorNames
descriptorsToImport += importableDescriptor
}
}

View File

@@ -6,54 +6,71 @@
package org.jetbrains.kotlin.idea.inspections
import com.intellij.codeInspection.IntentionWrapper
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING
import com.intellij.codeInspection.ProblemHighlightType.INFORMATION
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.intentions.AddNameToArgumentIntention
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.kotlin.psi.KtValueArgument
import org.jetbrains.kotlin.idea.intentions.AddNamesToCallArgumentsIntention
import org.jetbrains.kotlin.idea.intentions.AddNamesToFollowingArgumentsIntention
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.valueArgumentVisitor
import javax.swing.JComponent
class BooleanLiteralArgumentInspection(
@JvmField var reportSingle: Boolean = false
) : AbstractKotlinInspection() {
private fun KtExpression.isBooleanLiteral(): Boolean =
this is KtConstantExpression && node.elementType == KtNodeTypes.BOOLEAN_CONSTANT
private fun KtValueArgument.isUnnamedBooleanLiteral(): Boolean =
!isNamed() && getArgumentExpression()?.isBooleanLiteral() == true
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) =
valueArgumentVisitor(fun(argument: KtValueArgument) {
if (argument.getArgumentName() != null) return
val argumentExpression = argument.getArgumentExpression() as? KtConstantExpression ?: return
if (argumentExpression.node.elementType != KtNodeTypes.BOOLEAN_CONSTANT) return
if (argument.isNamed()) return
val argumentExpression = argument.getArgumentExpression() ?: return
if (!argumentExpression.isBooleanLiteral()) return
val call = argument.getStrictParentOfType<KtCallExpression>() ?: return
val valueArguments = call.valueArguments
if (valueArguments.takeLastWhile { it != argument }.any { !it.isNamed() }) return
if (argumentExpression.analyze().diagnostics.forElement(argumentExpression).any { it.severity == Severity.ERROR }) return
if (AddNameToArgumentIntention.detectNameToAdd(argument) == null) return
if (AddNameToArgumentIntention.detectNameToAdd(argument, shouldBeLastUnnamed = false) == null) return
val hasPreviousUnnamedBoolean = valueArguments.asSequence().windowed(size = 2, step = 1).any { (prev, next) ->
next == argument && !prev.isNamed() &&
(prev.getArgumentExpression() as? KtConstantExpression)?.node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT
val resolvedCall = call.resolveToCall() ?: return
if (!resolvedCall.candidateDescriptor.hasStableParameterNames()) return
val languageVersionSettings = call.languageVersionSettings
if (valueArguments.any {
!AddNameToArgumentIntention.argumentMatchedAndCouldBeNamedInCall(it, resolvedCall, languageVersionSettings)
}
) return
val highlightType = if (reportSingle) {
GENERIC_ERROR_OR_WARNING
} else {
val hasNeighbourUnnamedBoolean = valueArguments.asSequence().windowed(size = 2, step = 1).any { (prev, next) ->
prev == argument && next.isUnnamedBooleanLiteral() ||
next == argument && prev.isUnnamedBooleanLiteral()
}
if (hasNeighbourUnnamedBoolean) GENERIC_ERROR_OR_WARNING else INFORMATION
}
val fixes = mutableListOf<LocalQuickFix>()
if (hasPreviousUnnamedBoolean) {
fixes += AddNamesToLastBooleanArgumentsFix()
val fix = if (argument != valueArguments.lastOrNull { !it.isNamed() }) {
if (argument == valueArguments.firstOrNull()) {
IntentionWrapper(AddNamesToCallArgumentsIntention(), argument.containingKtFile)
} else {
IntentionWrapper(AddNamesToFollowingArgumentsIntention(), argument.containingKtFile)
}
} else {
IntentionWrapper(AddNameToArgumentIntention(), argument.containingKtFile)
}
fixes += IntentionWrapper(AddNameToArgumentIntention(), argument.containingKtFile)
holder.registerProblemWithoutOfflineInformation(
argument,
"Boolean literal argument without parameter name",
isOnTheFly,
if (reportSingle || hasPreviousUnnamedBoolean) GENERIC_ERROR_OR_WARNING else INFORMATION,
*fixes.toTypedArray()
argument, "Boolean literal argument without parameter name",
isOnTheFly, highlightType, fix
)
})
@@ -62,28 +79,4 @@ class BooleanLiteralArgumentInspection(
panel.addCheckbox("Report also on call with single boolean literal argument", "reportSingle")
return panel
}
private class AddNamesToLastBooleanArgumentsFix : LocalQuickFix {
override fun getFamilyName(): String = name
override fun getName() = "Add names to boolean arguments"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val argument = descriptor.psiElement as? KtValueArgument ?: return
val call = argument.getStrictParentOfType<KtCallExpression>() ?: return
val valueArguments = call.valueArguments
var problemArgumentFound = false
for (currentArgument in valueArguments.reversed()) {
if (currentArgument == argument) {
problemArgumentFound = true
} else if (!problemArgumentFound) continue
if (currentArgument.isNamed()) return
if ((currentArgument.getArgumentExpression() as? KtConstantExpression)?.node?.elementType != KtNodeTypes.BOOLEAN_CONSTANT) {
return
}
if (!AddNameToArgumentIntention.apply(currentArgument)) return
}
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.inspections
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElementVisitor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
class ConvertNaNEqualityInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return binaryExpressionVisitor { expression ->
if (expression.left.isNaNExpression() || expression.right.isNaNExpression()) {
val inverted = when (expression.operationToken) {
KtTokens.EXCLEQ -> true
KtTokens.EQEQ -> false
else -> return@binaryExpressionVisitor
}
holder.registerProblem(
expression,
"Equality check with NaN should be replaced with 'isNaN()'",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
ConvertNaNEqualityQuickFix(inverted)
)
}
}
}
}
private class ConvertNaNEqualityQuickFix(val inverted: Boolean) : LocalQuickFix {
override fun getName() = "Replace with 'isNaN()'"
override fun getFamilyName() = name
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.psiElement as? KtBinaryExpression ?: return
val other = when {
element.left.isNaNExpression() -> element.right ?: return
element.right.isNaNExpression() -> element.left ?: return
else -> return
}
val pattern = if (inverted) "!$0.isNaN()" else "$0.isNaN()"
element.replace(KtPsiFactory(element).createExpressionByPattern(pattern, other))
}
}
private val NaNSet = setOf("kotlin.Double.Companion.NaN", "java.lang.Double.NaN", "kotlin.Float.Companion.NaN", "java.lang.Float.NaN")
private fun KtExpression?.isNaNExpression(): Boolean {
if (this?.text?.endsWith("NaN") != true) return false
val fqName = this.resolveToCall()?.resultingDescriptor?.fqNameUnsafe?.asString()
return NaNSet.contains(fqName)
}

View File

@@ -16,21 +16,33 @@
package org.jetbrains.kotlin.idea.inspections
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.core.getModalityFromDescriptor
import org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.types.typeUtil.isNullableNothing
class ImplicitNullableNothingTypeInspection : IntentionBasedInspection<KtCallableDeclaration>(
intention = SpecifyTypeExplicitlyIntention::class,
additionalChecker = { declaration ->
SpecifyTypeExplicitlyIntention.getTypeForDeclaration(declaration).isNullableNothing() &&
(declaration.getModalityFromDescriptor() == KtTokens.OPEN_KEYWORD ||
declaration is KtProperty && declaration.isVar)
},
problemText = "Implicit `Nothing?` type"
intention = SpecifyTypeExplicitlyIntention::class,
additionalChecker = { declaration -> declaration.check() },
problemText = "Implicit `Nothing?` type"
) {
override fun inspectionTarget(element: KtCallableDeclaration) = element.nameIdentifier
}
private fun KtCallableDeclaration.check(): Boolean {
if (!SpecifyTypeExplicitlyIntention.getTypeForDeclaration(this).isNullableNothing()) return false
val descriptor = this.resolveToDescriptorIfAny()
return (getModalityFromDescriptor(descriptor) == KtTokens.OPEN_KEYWORD || this is KtProperty && this.isVar) &&
!isOverridingNullableNothing(descriptor)
}
private fun KtCallableDeclaration.isOverridingNullableNothing(descriptor: DeclarationDescriptor?): Boolean {
return hasModifier(KtTokens.OVERRIDE_KEYWORD) &&
(descriptor as? CallableMemberDescriptor)?.overriddenDescriptors?.any { it.returnType?.isNullableNothing() == true } == true
}

View File

@@ -49,7 +49,6 @@ import org.jetbrains.kotlin.idea.imports.OptimizedImportsBuilder
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtImportDirective
@@ -75,12 +74,10 @@ class KotlinUnusedImportInspection : AbstractKotlinInspection() {
.map { it.fqName }
.toSet()
val fqNames = HashMap<FqName, Set<Name>>()
val fqNames = optimizerData.namesToImport
val parentFqNames = HashSet<FqName>()
for ((descriptor, names) in optimizerData.descriptorsToImport) {
for (descriptor in optimizerData.descriptorsToImport) {
val fqName = descriptor.importableFqName!!
fqNames.compute(fqName) { _, u -> u?.plus(names) ?: names }
if (fqName !in explicitlyImportedFqNames) { // we don't add parents of explicitly imported fq-names because such imports are not needed
val parentFqName = fqName.parent()
if (!parentFqName.isRoot) {

View File

@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -68,7 +69,12 @@ private class RemoveRequireNotNullCallFix(private val functionName: String) : Lo
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val callExpression = descriptor.psiElement.getStrictParentOfType<KtCallExpression>() ?: return
val qualifiedExpression = callExpression.getQualifiedExpressionForSelector()
(qualifiedExpression ?: callExpression).delete()
val argument = callExpression.valueArguments.firstOrNull()?.getArgumentExpression() ?: return
val target = callExpression.getQualifiedExpressionForSelector() ?: callExpression
if (callExpression.isUsedAsExpression(callExpression.analyze(BodyResolveMode.PARTIAL))) {
target.replace(argument)
} else {
target.delete()
}
}
}

View File

@@ -65,7 +65,9 @@ class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspecti
val valueArguments = call.valueArguments
val typeArguments = call.typeArgumentList?.text ?: ""
if (replacement.toExtensionFunction) {
val receiverText = valueArguments.first().text
val receiverText = valueArguments.first().getArgumentExpression()
?.run { if (this is KtOperationExpression) "($text)" else text }
?: valueArguments.first().text
val argumentsText = valueArguments.drop(1).joinToString(separator = ", ") { it.text }
dotQualified.replaced(psiFactory.createExpression("$receiverText.${replacement.kotlinFunctionShortName}$typeArguments($argumentsText)"))
file.resolveImportReference(FqName(replacement.kotlinFunctionFqName)).firstOrNull()?.let {

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.idea.conversion.copy.start
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespace
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus.SUCCESS
@@ -40,7 +42,7 @@ class AddNameToArgumentIntention : SelfTargetingIntention<KtValueArgument>(
override fun isApplicableTo(element: KtValueArgument, caretOffset: Int): Boolean {
val expression = element.getArgumentExpression() ?: return false
val name = detectNameToAdd(element) ?: return false
val name = detectNameToAdd(element, shouldBeLastUnnamed = true) ?: return false
text = "Add '$name =' to argument"
@@ -60,24 +62,30 @@ class AddNameToArgumentIntention : SelfTargetingIntention<KtValueArgument>(
}
companion object {
fun apply(element: KtValueArgument): Boolean {
val name = detectNameToAdd(element) ?: return false
fun apply(element: KtValueArgument, givenResolvedCall: ResolvedCall<*>? = null): Boolean {
val name = detectNameToAdd(element, shouldBeLastUnnamed = false, givenResolvedCall = givenResolvedCall) ?: return false
val argumentExpression = element.getArgumentExpression() ?: return false
val prevSibling = element.getPrevSiblingIgnoringWhitespace()
if (prevSibling is PsiComment && """/\*\s*$name\s*=\s*\*/""".toRegex().matches(prevSibling.text)) {
prevSibling.delete()
}
val newArgument = KtPsiFactory(element).createArgument(argumentExpression, name, element.getSpreadElement() != null)
element.replace(newArgument)
return true
}
fun detectNameToAdd(argument: KtValueArgument): Name? {
fun detectNameToAdd(argument: KtValueArgument, shouldBeLastUnnamed: Boolean, givenResolvedCall: ResolvedCall<*>? = null): Name? {
if (argument.isNamed()) return null
if (argument is KtLambdaArgument) return null
val argumentList = argument.parent as? KtValueArgumentList ?: return null
if (argument != argumentList.arguments.last { !it.isNamed() }) return null
if (shouldBeLastUnnamed && argument != argumentList.arguments.last { !it.isNamed() }) return null
val callExpr = argumentList.parent as? KtCallElement ?: return null
val resolvedCall = callExpr.resolveToCall() ?: return null
if (!resolvedCall.resultingDescriptor.hasStableParameterNames()) return null
val resolvedCall = givenResolvedCall ?: callExpr.resolveToCall() ?: return null
if (!resolvedCall.candidateDescriptor.hasStableParameterNames()) return null
if (!argumentMatchedAndCouldBeNamedInCall(argument, resolvedCall, callExpr.languageVersionSettings)) return null

View File

@@ -21,7 +21,8 @@ import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
class AddNamesToCallArgumentsIntention : SelfTargetingRangeIntention<KtCallElement>(
KtCallElement::class.java,
@@ -32,13 +33,16 @@ class AddNamesToCallArgumentsIntention : SelfTargetingRangeIntention<KtCallEleme
if (arguments.all { it.isNamed() || it is LambdaArgument }) return null
val resolvedCall = element.resolveToCall() ?: return null
if (!resolvedCall.resultingDescriptor.hasStableParameterNames()) return null
if (!resolvedCall.candidateDescriptor.hasStableParameterNames()) return null
if (arguments.all {
AddNameToArgumentIntention.argumentMatchedAndCouldBeNamedInCall(it, resolvedCall, element.languageVersionSettings)
}
) {
return element.calleeExpression?.textRange
val calleeExpression = element.calleeExpression ?: return null
if (arguments.size < 2) return calleeExpression.textRange
val endOffset = (arguments.firstOrNull() as? KtValueArgument)?.endOffset ?: return null
return TextRange(calleeExpression.startOffset, endOffset)
}
return null
@@ -49,14 +53,7 @@ class AddNamesToCallArgumentsIntention : SelfTargetingRangeIntention<KtCallEleme
val resolvedCall = element.resolveToCall() ?: return
for (argument in arguments) {
if (argument !is KtValueArgument || argument is KtLambdaArgument) continue
val argumentMatch = resolvedCall.getArgumentMapping(argument) as? ArgumentMatch ?: continue
val name = argumentMatch.valueParameter.name
val newArgument = KtPsiFactory(element).createArgument(
argument.getArgumentExpression()!!,
name,
argument.getSpreadElement() != null
)
argument.replace(newArgument)
AddNameToArgumentIntention.apply(argument, resolvedCall)
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* 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.intentions
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.conversion.copy.end
import org.jetbrains.kotlin.idea.conversion.copy.start
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtValueArgument
import org.jetbrains.kotlin.psi.KtValueArgumentList
class AddNamesToFollowingArgumentsIntention : SelfTargetingIntention<KtValueArgument>(
KtValueArgument::class.java, "Add names to this argument and following arguments"
), LowPriorityAction {
override fun isApplicableTo(element: KtValueArgument, caretOffset: Int): Boolean {
val argumentList = element.parent as? KtValueArgumentList ?: return false
// Shadowed by AddNamesToCallArguments
if (argumentList.arguments.firstOrNull() == element) return false
// Shadowed by AddNameToArgument
if (argumentList.arguments.lastOrNull { !it.isNamed() } == element) return false
val expression = element.getArgumentExpression() ?: return false
AddNameToArgumentIntention.detectNameToAdd(element, shouldBeLastUnnamed = false) ?: return false
if (expression is KtLambdaExpression) {
val range = expression.textRange
return caretOffset == range.start || caretOffset == range.end
}
return true
}
override fun applyTo(element: KtValueArgument, editor: Editor?) {
val argumentList = element.parent as? KtValueArgumentList ?: return
val callElement = argumentList.parent as? KtCallElement ?: return
val resolvedCall = callElement.resolveToCall() ?: return
for (argument in argumentList.arguments.dropWhile { it != element }) {
AddNameToArgumentIntention.apply(argument, resolvedCall)
}
}
}

View File

@@ -113,7 +113,7 @@ fun provideTypeHint(element: KtCallableDeclaration, offset: Int): List<InlayInfo
}
append(getInlayHintsTypeRenderer(element.analyze(), element).renderType(type))
}
listOf(InlayInfo(declString, offset, false, true, true))
listOf(InlayInfo(declString, offset, isShowOnlyIfExistedBefore = false, isFilterByBlacklist = true, relatesToPrecedingText = true))
} else {
emptyList()
}

View File

@@ -105,7 +105,7 @@ private fun getActualTargetList(annotated: PsiTarget): AnnotationChecker.Compani
else -> T_MEMBER_FUNCTION
}
is PsiExpression -> T_EXPRESSION
is PsiField -> T_MEMBER_PROPERTY(true, false)
is PsiField -> T_MEMBER_PROPERTY(backingField = true, delegate = false)
is PsiLocalVariable -> T_LOCAL_VARIABLE
is PsiParameter -> T_VALUE_PARAMETER_WITHOUT_VAL
else -> EMPTY

View File

@@ -1,64 +1,97 @@
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.actions.OptimizeImportsProcessor
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.load.java.components.JavaAnnotationMapper
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtValueArgument
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
internal class DeprecatedJavaAnnotationFix(element: KtAnnotationEntry,
private val annotationFqName: FqName,
private val arguments: List<KtValueArgument>) : KotlinQuickFixAction<KtAnnotationEntry>(element) {
internal class DeprecatedJavaAnnotationFix(
element: KtAnnotationEntry,
private val annotationFqName: FqName
) : KotlinQuickFixAction<KtAnnotationEntry>(element) {
override fun getFamilyName() = "Replace Annotation"
override fun getText(): String = "Replace annotation with ${annotationFqName.asString()}"
override fun startInWriteAction(): Boolean = false
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val psiFactory = KtPsiFactory(project)
val argumentString = if(arguments.isEmpty()) {
""
} else {
"("+ arguments.joinToString(",") { it.text } + ")"
val arguments = updateAnnotation(psiFactory)
val replacementAnnotation = psiFactory.createAnnotationEntry("@$annotationFqName")
val valueArgumentList = psiFactory.buildValueArgumentList {
appendFixedText("(")
arguments.forEach { argument ->
appendExpression(argument.getArgumentExpression())
}
appendFixedText(")")
}
element.replace(psiFactory.createAnnotationEntry("@" + annotationFqName.shortName() + argumentString))
if (arguments.isNotEmpty()) {
replacementAnnotation.add(valueArgumentList)
}
for ((java, kotlin) in JavaAnnotationMapper.javaToKotlinNameMap) {
if (kotlin == annotationFqName) {
val oldImport = file.importDirectives.find { it -> it.importedFqName == java } ?: return
oldImport.delete()
break
val replaced = runWriteAction {
element.replaced(replacementAnnotation)
}
OptimizeImportsProcessor(project, file).run()
runWriteAction {
ShortenReferences.DEFAULT.process(replaced)
}
}
private fun updateAnnotation(psiFactory: KtPsiFactory): List<KtValueArgument> {
val bindingContext = element?.analyze() ?: return emptyList()
val descriptor = bindingContext[BindingContext.ANNOTATION, element]
val name = descriptor?.fqName ?: return emptyList()
val argumentOutput = mutableListOf<KtValueArgument>()
if (name == RETENTION_FQ_NAME) {
for (arg in descriptor.allValueArguments.values) {
val typeAndValue = arg.value as? Pair<*, *>
val classId = typeAndValue?.first as? ClassId
val value = typeAndValue?.second
if (classId == RETENTION_POLICY_ID) {
val argument = when ((value as? Name)?.asString()) {
"SOURCE" -> psiFactory.createArgument("kotlin.annotation.AnnotationRetention.SOURCE")
"CLASS" -> psiFactory.createArgument("kotlin.annotation.AnnotationRetention.BINARY")
"RUNTIME" -> psiFactory.createArgument("kotlin.annotation.AnnotationRetention.RUNTIME")
else -> psiFactory.createArgument("${classId.shortClassName}.$value")
}
argumentOutput.add(argument)
}
}
}
file.importList?.add(psiFactory.createImportDirective(ImportPath(annotationFqName, false, null)))
return argumentOutput
}
companion object Factory : KotlinSingleIntentionActionFactory() {
private val RETENTION_FQ_NAME = FqName("java.lang.annotation.Retention")
private val RETENTION_POLICY_ID = ClassId(FqName("java.lang.annotation"), FqName("RetentionPolicy"), false)
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val castedDiagnostic = ErrorsJvm.DEPRECATED_JAVA_ANNOTATION.cast(diagnostic)
val updatedAnnotation = castedDiagnostic.a as? FqName ?: return null
val entry = diagnostic.psiElement as? KtAnnotationEntry ?: return null
val arguments = mutableListOf<KtValueArgument>()
entry.valueArguments.forEach {
(it as KtValueArgument).children.forEach { child ->
arguments.add(child.context as KtValueArgument)
}
}
return DeprecatedJavaAnnotationFix(entry, updatedAnnotation, arguments)
return DeprecatedJavaAnnotationFix(entry, updatedAnnotation)
}
}

View File

@@ -26,6 +26,7 @@ import com.intellij.psi.PsiReferenceBase
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.idea.util.runWhenSmart
import org.jetbrains.kotlin.psi.KtElement
@@ -36,6 +37,8 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
object KotlinAddOrderEntryActionFactory : KotlinIntentionActionsFactory() {
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
val simpleExpression = diagnostic.psiElement as? KtSimpleNameExpression ?: return emptyList()
if (ProjectRootsUtil.isInProjectSource(simpleExpression, includeScriptsOutsideSourceRoots = false)) return emptyList()
val refElement = simpleExpression.getQualifiedElement()
val reference = object: PsiReferenceBase<KtElement>(refElement) {

View File

@@ -130,7 +130,7 @@ abstract class TypeInfo(val variance: Variance) {
return Collections.singletonList(callableBuilder.currentFileModule.builtIns.anyType)
}
val scope = getScopeForTypeApproximation(callableBuilder.config, callableBuilder.placement)
val approximations = getResolvableApproximations(scope, false, true)
val approximations = getResolvableApproximations(scope, checkTypeParameters = false, allowIntersections = true)
return when (variance) {
Variance.IN_VARIANCE -> approximations.toList()
else -> listOf(approximations.firstOrNull() ?: this)

View File

@@ -125,8 +125,8 @@ internal class ChangeMethodParameters(
ValueParameterDescriptorImpl(
this, null, index, Annotations.EMPTY,
Name.identifier(parameter.name),
parameter.ktType, false,
false, false, null, SourceElement.NO_SOURCE
parameter.ktType, declaresDefaultValue = false,
isCrossinline = false, isNoinline = false, varargElementType = null, source = SourceElement.NO_SOURCE
)
},
functionDescriptor.returnType,

View File

@@ -210,7 +210,12 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor {
val result = LinkedHashSet<PsiReference>()
val searchScope = functionPsi.useScope
val options = KotlinReferencesSearchOptions(true, false, false, false)
val options = KotlinReferencesSearchOptions(
acceptCallableOverrides = true,
acceptOverloads = false,
acceptExtensionsOfDeclarationClass = false,
acceptCompanionObjectMembers = false
)
val parameters = KotlinReferencesSearchParameters(functionPsi, searchScope, false, null, options)
result.addAll(ReferencesSearch.search(parameters).findAll())
if (functionPsi is KtProperty || functionPsi is KtParameter) {

View File

@@ -37,14 +37,14 @@ import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
class KotlinAwareDelegatingMoveDestination(
private val delegate: MoveDestination,
private val targetPackage: PsiPackage?,
private val targetDirectory: PsiDirectory?
private val delegate: MoveDestination,
private val targetPackage: PsiPackage?,
private val targetDirectory: PsiDirectory?
) : MoveDestination by delegate {
override fun analyzeModuleConflicts(
elements: MutableCollection<PsiElement>,
conflicts: MultiMap<PsiElement, String>,
usages: Array<out UsageInfo>
elements: MutableCollection<PsiElement>,
conflicts: MultiMap<PsiElement, String>,
usages: Array<out UsageInfo>
) {
delegate.analyzeModuleConflicts(elements, conflicts, usages)
@@ -71,7 +71,7 @@ class KotlinAwareDelegatingMoveDestination(
super.visitElement(element)
}
}
filesToProcess.flatMap {it.declarations}.forEach { it.accept(extraElementCollector) }
filesToProcess.flatMap { it.declarations }.forEach { it.accept(extraElementCollector) }
val progressIndicator = ProgressManager.getInstance().progressIndicator!!
progressIndicator.pushState()
@@ -80,13 +80,12 @@ class KotlinAwareDelegatingMoveDestination(
try {
progressIndicator.text = "Looking for Usages"
for ((index, element) in extraElementsForReferenceSearch.withIndex()) {
progressIndicator.fraction = (index + 1)/extraElementsForReferenceSearch.size.toDouble()
progressIndicator.fraction = (index + 1) / extraElementsForReferenceSearch.size.toDouble()
ReferencesSearch.search(element, projectScope).mapNotNullTo(extraUsages) { ref ->
createMoveUsageInfoIfPossible(ref, element, true, false)
createMoveUsageInfoIfPossible(ref, element, addImportToOriginalFile = true, isInternal = false)
}
}
}
finally {
} finally {
progressIndicator.popState()
}

View File

@@ -81,8 +81,7 @@ interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
val container = originalElement.containingClassOrObject
if (container is KtObjectDeclaration && container.isCompanion() && container.declarations.singleOrNull() == originalElement) {
container.deleteSingle()
}
else {
} else {
originalElement.deleteSingle()
}
}
@@ -142,11 +141,12 @@ private object ElementHashingStrategy : TObjectHashingStrategy<PsiElement> {
}
class MoveKotlinDeclarationsProcessor(
val descriptor: MoveDeclarationsDescriptor,
val mover: Mover = Mover.Default) : BaseRefactoringProcessor(descriptor.project) {
val descriptor: MoveDeclarationsDescriptor,
val mover: Mover = Mover.Default
) : BaseRefactoringProcessor(descriptor.project) {
companion object {
private val REFACTORING_NAME = "Move declarations"
val REFACTORING_ID = "move.kotlin.declarations"
private const val REFACTORING_NAME = "Move declarations"
const val REFACTORING_ID = "move.kotlin.declarations"
}
val project get() = descriptor.project
@@ -155,8 +155,8 @@ class MoveKotlinDeclarationsProcessor(
private val moveEntireFile = descriptor.moveSource is MoveSource.File
private val elementsToMove = descriptor.moveSource.elementsToMove.filter { e -> e.parent != descriptor.moveTarget.getTargetPsiIfExists(e) }
private val kotlinToLightElementsBySourceFile = elementsToMove
.groupBy { it.containingKtFile }
.mapValues { it.value.keysToMap { it.toLightElements().ifEmpty { listOf(it) } } }
.groupBy { it.containingKtFile }
.mapValues { it.value.keysToMap { it.toLightElements().ifEmpty { listOf(it) } } }
private val conflicts = MultiMap<PsiElement, String>()
override fun getRefactoringId() = REFACTORING_ID
@@ -207,23 +207,23 @@ class MoveKotlinDeclarationsProcessor(
val foundReferences = HashSet<PsiReference>()
val results = ReferencesSearch
.search(lightElement, searchScope)
.mapNotNullTo(ArrayList()) { ref ->
if (foundReferences.add(ref) && elementsToMove.none { it.isAncestor(ref.element)}) {
createMoveUsageInfoIfPossible(ref, lightElement, true, false)
}
else null
.search(lightElement, searchScope)
.mapNotNullTo(ArrayList()) { ref ->
if (foundReferences.add(ref) && elementsToMove.none { it.isAncestor(ref.element)}) {
createMoveUsageInfoIfPossible(ref, lightElement, addImportToOriginalFile = true, isInternal = false)
}
else null
}
val name = lightElement.getKotlinFqName()?.quoteIfNeeded()?.asString()
if (name != null) {
TextOccurrencesUtil.findNonCodeUsages(
lightElement,
name,
descriptor.searchInCommentsAndStrings,
descriptor.searchInNonCode,
FqName(newFqName).quoteIfNeeded().asString(),
results
lightElement,
name,
descriptor.searchInCommentsAndStrings,
descriptor.searchInNonCode,
FqName(newFqName).quoteIfNeeded().asString(),
results
)
}
@@ -237,11 +237,11 @@ class MoveKotlinDeclarationsProcessor(
val usages = ArrayList<UsageInfo>()
val conflictChecker = MoveConflictChecker(
project,
elementsToMove,
descriptor.moveTarget,
elementsToMove.first(),
allElementsToMove = descriptor.allElementsToMove
project,
elementsToMove,
descriptor.moveTarget,
elementsToMove.first(),
allElementsToMove = descriptor.allElementsToMove
)
for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
val internalUsages = LinkedHashSet<UsageInfo>()
@@ -249,12 +249,11 @@ class MoveKotlinDeclarationsProcessor(
if (moveEntireFile) {
val changeInfo = ContainerChangeInfo(
ContainerInfo.Package(sourceFile.packageFqName),
descriptor.moveTarget.targetContainerFqName?.let { ContainerInfo.Package(it) } ?: ContainerInfo.UnknownPackage
ContainerInfo.Package(sourceFile.packageFqName),
descriptor.moveTarget.targetContainerFqName?.let { ContainerInfo.Package(it) } ?: ContainerInfo.UnknownPackage
)
internalUsages += sourceFile.getInternalReferencesToUpdateOnPackageNameChange(changeInfo)
}
else {
} else {
kotlinToLightElements.keys.forEach {
val packageNameInfo = descriptor.delegate.getContainerChangeInfo(it, descriptor.moveTarget)
internalUsages += it.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
@@ -284,7 +283,7 @@ class MoveKotlinDeclarationsProcessor(
internal fun doPerformRefactoring(usages: List<UsageInfo>) {
fun moveDeclaration(declaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): KtNamedDeclaration {
val targetContainer = moveTarget.getOrCreateTargetPsi(declaration)
?: throw AssertionError("Couldn't create Kotlin file for: ${declaration::class.java}: ${declaration.text}")
?: throw AssertionError("Couldn't create Kotlin file for: ${declaration::class.java}: ${declaration.text}")
descriptor.delegate.preprocessDeclaration(descriptor, declaration)
if (moveEntireFile) return declaration
return mover(declaration, targetContainer).apply {
@@ -341,12 +340,10 @@ class MoveKotlinDeclarationsProcessor(
usagesToProcess += newInternalUsages
nonCodeUsages = postProcessMoveUsages(usagesToProcess, oldToNewElementsMapping).toTypedArray()
}
catch (e: IncorrectOperationException) {
} catch (e: IncorrectOperationException) {
nonCodeUsages = null
RefactoringUIUtil.processIncorrectOperation(myProject, e)
}
finally {
} finally {
cleanUpInternalUsages(newInternalUsages + oldInternalUsages)
}
}

View File

@@ -38,11 +38,11 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
fun invokeMoveFilesOrDirectoriesRefactoring(
moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?,
project: Project,
elements: Array<out PsiElement>,
initialTargetDirectory: PsiDirectory?,
moveCallback: MoveCallback?
moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?,
project: Project,
elements: Array<out PsiElement>,
initialTargetDirectory: PsiDirectory?,
moveCallback: MoveCallback?
) {
fun closeDialog() {
moveDialog?.close(DialogWrapper.CANCEL_EXIT_CODE)
@@ -55,19 +55,19 @@ fun invokeMoveFilesOrDirectoriesRefactoring(
try {
val choice = if (elements.size > 1 || elements[0] is PsiDirectory) intArrayOf(-1) else null
val elementsToMove = elements
.filterNot {
it is PsiFile
&& runWriteAction { CopyFilesOrDirectoriesHandler.checkFileExist(selectedDir, choice, it, it.name, "Move") }
.filterNot {
it is PsiFile
&& runWriteAction { CopyFilesOrDirectoriesHandler.checkFileExist(selectedDir, choice, it, it.name, "Move") }
}
.sortedWith( // process Kotlin files first so that light classes are updated before changing references in Java files
java.util.Comparator { o1, o2 ->
when {
o1 is KtElement && o2 !is KtElement -> -1
o1 !is KtElement && o2 is KtElement -> 1
else -> 0
}
}
.sortedWith( // process Kotlin files first so that light classes are updated before changing references in Java files
java.util.Comparator { o1, o2 ->
when {
o1 is KtElement && o2 !is KtElement -> -1
o1 !is KtElement && o2 is KtElement -> 1
else -> 0
}
}
)
)
elementsToMove.forEach {
MoveFilesOrDirectoriesUtil.checkMove(it, selectedDir)
@@ -79,22 +79,20 @@ fun invokeMoveFilesOrDirectoriesRefactoring(
if (elementsToMove.isNotEmpty()) {
@Suppress("UNCHECKED_CAST")
val processor = KotlinAwareMoveFilesOrDirectoriesProcessor(
project,
elementsToMove as List<KtFile>,
selectedDir,
moveDialog?.searchReferences ?: true,
false,
false,
moveCallback,
Runnable(::closeDialog)
project,
elementsToMove as List<KtFile>,
selectedDir,
searchReferences = moveDialog?.searchReferences ?: true,
searchInComments = false,
searchInNonJavaFiles = false,
moveCallback = moveCallback,
prepareSuccessfulCallback = Runnable(::closeDialog)
)
processor.run()
}
else {
} else {
closeDialog()
}
}
catch (e: IncorrectOperationException) {
} catch (e: IncorrectOperationException) {
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.message, "refactoring.moveFile", project)
}
}
@@ -102,12 +100,12 @@ fun invokeMoveFilesOrDirectoriesRefactoring(
// Mostly copied from MoveFilesOrDirectoriesUtil.doMove()
fun moveFilesOrDirectories(
project: Project,
elements: Array<PsiElement>,
targetElement: PsiElement?,
moveCallback: MoveCallback? = null
project: Project,
elements: Array<PsiElement>,
targetElement: PsiElement?,
moveCallback: MoveCallback? = null
) {
elements.forEach { if (it !is PsiFile && it !is PsiDirectory) throw IllegalArgumentException("unexpected element type: " + it) }
elements.forEach { if (it !is PsiFile && it !is PsiDirectory) throw IllegalArgumentException("unexpected element type: $it") }
val targetDirectory = MoveFilesOrDirectoriesUtil.resolveToDirectory(project, targetElement)
if (targetElement != null && targetDirectory == null) return

View File

@@ -185,7 +185,7 @@ fun KtElement.processInternalReferencesToUpdateOnPackageNameChange(
val declarationNotNull = declaration ?: return null
if (isExtension || containerFqName != null || isImported) return {
createMoveUsageInfoIfPossible(it.mainReference, declarationNotNull, false, true)
createMoveUsageInfoIfPossible(it.mainReference, declarationNotNull, addImportToOriginalFile = false, isInternal = true)
}
return null

View File

@@ -33,19 +33,20 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
fun wrapOrSkip(s: String, inCode: Boolean) = if (inCode) "<code>$s</code>" else s
fun formatClassDescriptor(classDescriptor: DeclarationDescriptor) = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.render(classDescriptor)
fun formatClassDescriptor(classDescriptor: DeclarationDescriptor) =
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.render(classDescriptor)
fun formatPsiClass(
psiClass: PsiClass,
markAsJava: Boolean,
inCode: Boolean
psiClass: PsiClass,
markAsJava: Boolean,
inCode: Boolean
): String {
var description: String
val kind = if (psiClass.isInterface) "interface " else "class "
description = kind + PsiFormatUtil.formatClass(
psiClass,
PsiFormatUtilBase.SHOW_CONTAINING_CLASS or PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
psiClass,
PsiFormatUtilBase.SHOW_CONTAINING_CLASS or PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
)
description = wrapOrSkip(description, inCode)
@@ -56,8 +57,7 @@ fun formatClass(classDescriptor: DeclarationDescriptor, inCode: Boolean): String
val element = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor)
return if (element is PsiClass) {
formatPsiClass(element, false, inCode)
}
else {
} else {
wrapOrSkip(formatClassDescriptor(classDescriptor), inCode)
}
}
@@ -66,8 +66,7 @@ fun formatFunction(functionDescriptor: DeclarationDescriptor, inCode: Boolean):
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)
return if (element is PsiMethod) {
formatPsiMethod(element, false, inCode)
}
else {
} else {
wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode)
}
}
@@ -75,9 +74,9 @@ fun formatFunction(functionDescriptor: DeclarationDescriptor, inCode: Boolean):
private fun formatFunctionDescriptor(functionDescriptor: DeclarationDescriptor) = DescriptorRenderer.COMPACT.render(functionDescriptor)
fun formatPsiMethod(
psiMethod: PsiMethod,
showContainingClass: Boolean,
inCode: Boolean
psiMethod: PsiMethod,
showContainingClass: Boolean,
inCode: Boolean
): String {
var options = PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
if (showContainingClass) {
@@ -95,9 +94,8 @@ fun formatJavaOrLightMethod(method: PsiMethod): String {
val originalDeclaration = method.unwrapped
return if (originalDeclaration is KtDeclaration) {
formatFunctionDescriptor(originalDeclaration.unsafeResolveToDescriptor())
}
else {
formatPsiMethod(method, false, false)
} else {
formatPsiMethod(method, showContainingClass = false, inCode = false)
}
}

View File

@@ -0,0 +1,9 @@
package pack1
fun a() {
}
fun Int.a() {
}

View File

@@ -0,0 +1,15 @@
import pack1.a
import pack1.a as a1
import kotlin.collections.List
import kotlin.collections.List as List1
import kotlin.run as run1
import kotlin.run
fun foo() {
run {}
run1 {}
List<String>(1) {}
List1<String>(1) {}
a()
a1()
}

View File

@@ -0,0 +1,15 @@
import pack1.a
import kotlin.collections.List
import kotlin.run
import pack1.a as a1
import kotlin.collections.List as List1
import kotlin.run as run1
fun foo() {
run {}
run1 {}
List<String>(1) {}
List1<String>(1) {}
a()
a1()
}

View File

@@ -0,0 +1,37 @@
Additional checking of reference Getter: List
Additional checking of reference KtSimpleNameReference: List
Additional checking of reference Getter: List1
Additional checking of reference KtSimpleNameReference: List1
Changed resolve of KtSimpleNameReference: List1
Additional checking of reference Getter: a1
Additional checking of reference KtSimpleNameReference: a1
Changed resolve of KtSimpleNameReference: a1
Additional checking of reference Getter: run
Additional checking of reference KtSimpleNameReference: run
Additional checking of reference Getter: run1
Additional checking of reference KtSimpleNameReference: run1
Changed resolve of KtSimpleNameReference: run1
Additional checking of reference KtInvokeFunctionReference: List1<String>(1) {}
Additional checking of reference KtInvokeFunctionReference: List<String>(1) {}
Additional checking of reference KtInvokeFunctionReference: a1()
Additional checking of reference KtInvokeFunctionReference: run {}
Additional checking of reference KtInvokeFunctionReference: run1 {}
Trying to build import list again with import rules: +pack1.a as a1, +kotlin.collections.List as List1, +kotlin.run as run1
Additional checking of reference Getter: List
Additional checking of reference KtSimpleNameReference: List
Additional checking of reference Getter: List1
Additional checking of reference KtSimpleNameReference: List1
Changed resolve of KtSimpleNameReference: List1
Additional checking of reference Getter: a1
Additional checking of reference KtSimpleNameReference: a1
Changed resolve of KtSimpleNameReference: a1
Additional checking of reference Getter: run
Additional checking of reference KtSimpleNameReference: run
Additional checking of reference Getter: run1
Additional checking of reference KtSimpleNameReference: run1
Changed resolve of KtSimpleNameReference: run1
Additional checking of reference KtInvokeFunctionReference: List1<String>(1) {}
Additional checking of reference KtInvokeFunctionReference: List<String>(1) {}
Additional checking of reference KtInvokeFunctionReference: a1()
Additional checking of reference KtInvokeFunctionReference: run {}
Additional checking of reference KtInvokeFunctionReference: run1 {}

View File

@@ -0,0 +1,9 @@
package pack1
fun a() {
}
fun Int.a() {
}

View File

@@ -0,0 +1,10 @@
import pack1.a
import pack1.a as a1
import kotlin.run as run1
import kotlin.run
fun foo() {
run1 {}
a()
42.a1()
}

View File

@@ -0,0 +1,9 @@
import pack1.a
import pack1.a as a1
import kotlin.run as run1
fun foo() {
run1 {}
a()
42.a1()
}

View File

@@ -0,0 +1,17 @@
Additional checking of reference Getter: a1
Additional checking of reference KtSimpleNameReference: a1
Changed resolve of KtSimpleNameReference: a1
Additional checking of reference Getter: run1
Additional checking of reference KtSimpleNameReference: run1
Changed resolve of KtSimpleNameReference: run1
Additional checking of reference KtInvokeFunctionReference: a1()
Additional checking of reference KtInvokeFunctionReference: run1 {}
Trying to build import list again with import rules: +pack1.a as a1, +kotlin.run as run1
Additional checking of reference Getter: a1
Additional checking of reference KtSimpleNameReference: a1
Changed resolve of KtSimpleNameReference: a1
Additional checking of reference Getter: run1
Additional checking of reference KtSimpleNameReference: run1
Changed resolve of KtSimpleNameReference: run1
Additional checking of reference KtInvokeFunctionReference: a1()
Additional checking of reference KtInvokeFunctionReference: run1 {}

View File

@@ -0,0 +1,7 @@
package a
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class C
operator fun C.provideDelegate(thisRef: Any, prop: KProperty<*>): ReadOnlyProperty<Any, C> = TODO()

View File

@@ -0,0 +1,8 @@
package b
import a.C
import a.provideDelegate
class Example {
val c: C = C()
}

View File

@@ -0,0 +1,7 @@
package b
import a.C
class Example {
val c: C = C()
}

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