Cleanup: apply "cascade if..." inspection (+ some others)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
9c06739594
commit
1d2017b0fc
@@ -292,14 +292,10 @@ fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingConte
|
|||||||
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression!!, ktType, bindingContext, descriptor)
|
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression!!, ktType, bindingContext, descriptor)
|
||||||
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow)
|
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow)
|
||||||
return stableTypes.firstNotNullResult {
|
return stableTypes.firstNotNullResult {
|
||||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(it)) {
|
when {
|
||||||
TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it))
|
KotlinBuiltIns.isDoubleOrNullableDouble(it) -> TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it))
|
||||||
}
|
KotlinBuiltIns.isFloatOrNullableFloat(it) -> TypeAndNullability(Type.FLOAT_TYPE, TypeUtils.isNullableType(it))
|
||||||
else if (KotlinBuiltIns.isFloatOrNullableFloat(it)) {
|
else -> null
|
||||||
TypeAndNullability(Type.FLOAT_TYPE, TypeUtils.isNullableType(it))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,18 +83,16 @@ private fun ExpressionCodegen.createOptimizedForLoopGeneratorOrNull(
|
|||||||
private fun getLoopRangeResolvedCall(forExpression: KtForExpression, bindingContext: BindingContext): ResolvedCall<out CallableDescriptor>? {
|
private fun getLoopRangeResolvedCall(forExpression: KtForExpression, bindingContext: BindingContext): ResolvedCall<out CallableDescriptor>? {
|
||||||
val loopRange = KtPsiUtil.deparenthesize(forExpression.loopRange)
|
val loopRange = KtPsiUtil.deparenthesize(forExpression.loopRange)
|
||||||
|
|
||||||
if (loopRange is KtQualifiedExpression) {
|
when (loopRange) {
|
||||||
val qualifiedExpression = loopRange as KtQualifiedExpression?
|
is KtQualifiedExpression -> {
|
||||||
val selector = qualifiedExpression!!.selectorExpression
|
val qualifiedExpression = loopRange as KtQualifiedExpression?
|
||||||
if (selector is KtCallExpression || selector is KtSimpleNameExpression) {
|
val selector = qualifiedExpression!!.selectorExpression
|
||||||
return selector.getResolvedCall(bindingContext)
|
if (selector is KtCallExpression || selector is KtSimpleNameExpression) {
|
||||||
|
return selector.getResolvedCall(bindingContext)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtSimpleNameExpression, is KtCallExpression -> return loopRange.getResolvedCall(bindingContext)
|
||||||
else if (loopRange is KtSimpleNameExpression || loopRange is KtCallExpression) {
|
is KtBinaryExpression -> return loopRange.operationReference.getResolvedCall(bindingContext)
|
||||||
return loopRange.getResolvedCall(bindingContext)
|
|
||||||
}
|
|
||||||
else if (loopRange is KtBinaryExpression) {
|
|
||||||
return loopRange.operationReference.getResolvedCall(bindingContext)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -610,14 +610,10 @@ class PsiInlineCodegen(
|
|||||||
|
|
||||||
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
|
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
|
||||||
activeLambda = next
|
activeLambda = next
|
||||||
if (next is ExpressionLambda) {
|
when (next) {
|
||||||
codegen.pushClosureOnStack(next.classDescriptor, true, this, functionReferenceReceiver)
|
is ExpressionLambda -> codegen.pushClosureOnStack(next.classDescriptor, true, this, functionReferenceReceiver)
|
||||||
}
|
is DefaultLambda -> rememberCapturedForDefaultLambda(next)
|
||||||
else if (next is DefaultLambda) {
|
else -> throw RuntimeException("Unknown lambda: $next")
|
||||||
rememberCapturedForDefaultLambda(next)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw RuntimeException("Unknown lambda: $next")
|
|
||||||
}
|
}
|
||||||
activeLambda = null
|
activeLambda = null
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-15
@@ -408,23 +408,27 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
sourceFile
|
sourceFile
|
||||||
)
|
)
|
||||||
|
|
||||||
if (descriptor is ScriptDescriptor) {
|
return when (descriptor) {
|
||||||
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
is ScriptDescriptor -> {
|
||||||
return parent.intoScript(
|
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
||||||
descriptor,
|
parent.intoScript(
|
||||||
earlierScripts ?: emptyList(),
|
descriptor,
|
||||||
descriptor as ClassDescriptor, state.typeMapper
|
earlierScripts ?: emptyList(),
|
||||||
)
|
descriptor as ClassDescriptor, state.typeMapper
|
||||||
}
|
)
|
||||||
else if (descriptor is ClassDescriptor) {
|
}
|
||||||
val kind = if (DescriptorUtils.isInterface(descriptor)) OwnerKind.DEFAULT_IMPLS else OwnerKind.IMPLEMENTATION
|
is ClassDescriptor -> {
|
||||||
return parent.intoClass(descriptor, kind, state)
|
val kind = if (DescriptorUtils.isInterface(descriptor)) OwnerKind.DEFAULT_IMPLS else OwnerKind.IMPLEMENTATION
|
||||||
}
|
parent.intoClass(descriptor, kind, state)
|
||||||
else if (descriptor is FunctionDescriptor) {
|
}
|
||||||
return parent.intoFunction(descriptor)
|
is FunctionDescriptor -> {
|
||||||
|
parent.intoFunction(descriptor)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw IllegalStateException("Couldn't build context for " + descriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw IllegalStateException("Couldn't build context for " + descriptor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,33 +171,35 @@ private fun getInlineName(
|
|||||||
typeMapper: KotlinTypeMapper,
|
typeMapper: KotlinTypeMapper,
|
||||||
fileClassesProvider: JvmFileClassesProvider
|
fileClassesProvider: JvmFileClassesProvider
|
||||||
): String {
|
): String {
|
||||||
if (currentDescriptor is PackageFragmentDescriptor) {
|
when (currentDescriptor) {
|
||||||
val file = DescriptorToSourceUtils.getContainingFile(codegenContext.contextDescriptor)
|
is PackageFragmentDescriptor -> {
|
||||||
|
val file = DescriptorToSourceUtils.getContainingFile(codegenContext.contextDescriptor)
|
||||||
|
|
||||||
val implementationOwnerType: Type? =
|
val implementationOwnerType: Type? =
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
CodegenContextUtil.getImplementationOwnerClassType(codegenContext)
|
CodegenContextUtil.getImplementationOwnerClassType(codegenContext)
|
||||||
}
|
}
|
||||||
else fileClassesProvider.getFileClassType(file)
|
else fileClassesProvider.getFileClassType(file)
|
||||||
|
|
||||||
if (implementationOwnerType == null) {
|
if (implementationOwnerType == null) {
|
||||||
val contextDescriptor = codegenContext.contextDescriptor
|
val contextDescriptor = codegenContext.contextDescriptor
|
||||||
throw RuntimeException(
|
throw RuntimeException(
|
||||||
"Couldn't find declaration for " +
|
"Couldn't find declaration for " +
|
||||||
contextDescriptor.containingDeclaration!!.name + "." + contextDescriptor.name +
|
contextDescriptor.containingDeclaration!!.name + "." + contextDescriptor.name +
|
||||||
"; context: " + codegenContext
|
"; context: " + codegenContext
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return implementationOwnerType.internalName
|
||||||
}
|
}
|
||||||
|
is ClassifierDescriptor -> {
|
||||||
return implementationOwnerType.internalName
|
return typeMapper.mapType(currentDescriptor).internalName
|
||||||
}
|
}
|
||||||
else if (currentDescriptor is ClassifierDescriptor) {
|
is FunctionDescriptor -> {
|
||||||
return typeMapper.mapType(currentDescriptor).internalName
|
val descriptor = typeMapper.bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, currentDescriptor)
|
||||||
}
|
if (descriptor != null) {
|
||||||
else if (currentDescriptor is FunctionDescriptor) {
|
return typeMapper.mapType(descriptor).internalName
|
||||||
val descriptor = typeMapper.bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, currentDescriptor)
|
}
|
||||||
if (descriptor != null) {
|
|
||||||
return typeMapper.mapType(descriptor).internalName
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,21 +43,23 @@ object JavaClassProperty : IntrinsicPropertyGetter() {
|
|||||||
|
|
||||||
fun generateImpl(v: InstructionAdapter, receiver: StackValue): Type {
|
fun generateImpl(v: InstructionAdapter, receiver: StackValue): Type {
|
||||||
val type = receiver.type
|
val type = receiver.type
|
||||||
if (type == Type.VOID_TYPE) {
|
when {
|
||||||
receiver.put(Type.VOID_TYPE, v)
|
type == Type.VOID_TYPE -> {
|
||||||
StackValue.unit().put(UNIT_TYPE, v)
|
receiver.put(Type.VOID_TYPE, v)
|
||||||
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
|
StackValue.unit().put(UNIT_TYPE, v)
|
||||||
}
|
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
|
||||||
else if (isPrimitive(type)) {
|
}
|
||||||
if (!StackValue.couldSkipReceiverOnStaticCall(receiver)) {
|
isPrimitive(type) -> {
|
||||||
receiver.put(type, v)
|
if (!StackValue.couldSkipReceiverOnStaticCall(receiver)) {
|
||||||
AsmUtil.pop(v, type)
|
receiver.put(type, v)
|
||||||
|
AsmUtil.pop(v, type)
|
||||||
|
}
|
||||||
|
v.getstatic(boxType(type).internalName, "TYPE", "Ljava/lang/Class;")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
receiver.put(type, v)
|
||||||
|
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
|
||||||
}
|
}
|
||||||
v.getstatic(boxType(type).internalName, "TYPE", "Ljava/lang/Class;")
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
receiver.put(type, v)
|
|
||||||
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getType(Class::class.java)
|
return getType(Class::class.java)
|
||||||
|
|||||||
@@ -1123,15 +1123,10 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
kind
|
kind
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (check(kind, existingKind, IN_TRY, TAIL_CALL)) {
|
when {
|
||||||
IN_TRY
|
check(kind, existingKind, IN_TRY, TAIL_CALL) -> IN_TRY
|
||||||
}
|
check(kind, existingKind, IN_TRY, NON_TAIL) -> IN_TRY
|
||||||
else if (check(kind, existingKind, IN_TRY, NON_TAIL)) {
|
else -> NON_TAIL // TAIL_CALL, NON_TAIL
|
||||||
IN_TRY
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TAIL_CALL, NON_TAIL
|
|
||||||
NON_TAIL
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,15 +107,17 @@ class UnreachableCodeImpl(
|
|||||||
currentTextRange, element ->
|
currentTextRange, element ->
|
||||||
|
|
||||||
val elementRange = element.textRange!!
|
val elementRange = element.textRange!!
|
||||||
if (currentTextRange == null) {
|
when {
|
||||||
elementRange
|
currentTextRange == null -> {
|
||||||
}
|
elementRange
|
||||||
else if (currentTextRange.endOffset == elementRange.startOffset) {
|
}
|
||||||
currentTextRange.union(elementRange)
|
currentTextRange.endOffset == elementRange.startOffset -> {
|
||||||
}
|
currentTextRange.union(elementRange)
|
||||||
else {
|
}
|
||||||
result.add(currentTextRange)
|
else -> {
|
||||||
elementRange
|
result.add(currentTextRange)
|
||||||
|
elementRange
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lastRange != null) {
|
if (lastRange != null) {
|
||||||
|
|||||||
+5
-1
@@ -47,4 +47,8 @@ class SyntheticFieldDescriptor private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val DeclarationDescriptor.referencedProperty: PropertyDescriptor?
|
val DeclarationDescriptor.referencedProperty: PropertyDescriptor?
|
||||||
get() = if (this is SyntheticFieldDescriptor) this.propertyDescriptor else if (this is PropertyDescriptor) this else null
|
get() = when (this) {
|
||||||
|
is SyntheticFieldDescriptor -> this.propertyDescriptor
|
||||||
|
is PropertyDescriptor -> this
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|||||||
@@ -458,7 +458,11 @@ object Renderers {
|
|||||||
|
|
||||||
private fun renderTypeBounds(typeBounds: TypeBounds, short: Boolean): String {
|
private fun renderTypeBounds(typeBounds: TypeBounds, short: Boolean): String {
|
||||||
val renderBound = { bound: Bound ->
|
val renderBound = { bound: Bound ->
|
||||||
val arrow = if (bound.kind == LOWER_BOUND) ">: " else if (bound.kind == UPPER_BOUND) "<: " else ":= "
|
val arrow = when (bound.kind) {
|
||||||
|
LOWER_BOUND -> ">: "
|
||||||
|
UPPER_BOUND -> "<: "
|
||||||
|
else -> ":= "
|
||||||
|
}
|
||||||
val renderer = if (short) DescriptorRenderer.SHORT_NAMES_IN_TYPES else DescriptorRenderer.FQ_NAMES_IN_TYPES
|
val renderer = if (short) DescriptorRenderer.SHORT_NAMES_IN_TYPES else DescriptorRenderer.FQ_NAMES_IN_TYPES
|
||||||
val renderedBound = arrow + renderer.renderType(bound.constrainingType) + if (!bound.isProper) "*" else ""
|
val renderedBound = arrow + renderer.renderType(bound.constrainingType) + if (!bound.isProper) "*" else ""
|
||||||
if (short) renderedBound else renderedBound + '(' + bound.position + ')'
|
if (short) renderedBound else renderedBound + '(' + bound.position + ')'
|
||||||
|
|||||||
@@ -202,32 +202,28 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
|
|||||||
(descriptor as? ClassDescriptor)?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER
|
(descriptor as? ClassDescriptor)?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER
|
||||||
is KtDestructuringDeclarationEntry -> TargetLists.T_LOCAL_VARIABLE
|
is KtDestructuringDeclarationEntry -> TargetLists.T_LOCAL_VARIABLE
|
||||||
is KtProperty -> {
|
is KtProperty -> {
|
||||||
if (annotated.isLocal)
|
when {
|
||||||
TargetLists.T_LOCAL_VARIABLE
|
annotated.isLocal -> TargetLists.T_LOCAL_VARIABLE
|
||||||
else if (annotated.isMember)
|
annotated.isMember -> TargetLists.T_MEMBER_PROPERTY(descriptor.hasBackingField(trace), annotated.hasDelegate())
|
||||||
TargetLists.T_MEMBER_PROPERTY(descriptor.hasBackingField(trace), annotated.hasDelegate())
|
else -> TargetLists.T_TOP_LEVEL_PROPERTY(descriptor.hasBackingField(trace), annotated.hasDelegate())
|
||||||
else
|
}
|
||||||
TargetLists.T_TOP_LEVEL_PROPERTY(descriptor.hasBackingField(trace), annotated.hasDelegate())
|
|
||||||
}
|
}
|
||||||
is KtParameter -> {
|
is KtParameter -> {
|
||||||
val destructuringDeclaration = annotated.destructuringDeclaration
|
val destructuringDeclaration = annotated.destructuringDeclaration
|
||||||
if (destructuringDeclaration != null)
|
when {
|
||||||
TargetLists.T_DESTRUCTURING_DECLARATION
|
destructuringDeclaration != null -> TargetLists.T_DESTRUCTURING_DECLARATION
|
||||||
else if (annotated.hasValOrVar())
|
annotated.hasValOrVar() -> TargetLists.T_VALUE_PARAMETER_WITH_VAL
|
||||||
TargetLists.T_VALUE_PARAMETER_WITH_VAL
|
else -> TargetLists.T_VALUE_PARAMETER_WITHOUT_VAL
|
||||||
else
|
}
|
||||||
TargetLists.T_VALUE_PARAMETER_WITHOUT_VAL
|
|
||||||
}
|
}
|
||||||
is KtConstructor<*> -> TargetLists.T_CONSTRUCTOR
|
is KtConstructor<*> -> TargetLists.T_CONSTRUCTOR
|
||||||
is KtFunction -> {
|
is KtFunction -> {
|
||||||
if (ExpressionTypingUtils.isFunctionExpression(descriptor))
|
when {
|
||||||
TargetLists.T_FUNCTION_EXPRESSION
|
ExpressionTypingUtils.isFunctionExpression(descriptor) -> TargetLists.T_FUNCTION_EXPRESSION
|
||||||
else if (annotated.isLocal)
|
annotated.isLocal -> TargetLists.T_LOCAL_FUNCTION
|
||||||
TargetLists.T_LOCAL_FUNCTION
|
annotated.parent is KtClassOrObject || annotated.parent is KtClassBody -> TargetLists.T_MEMBER_FUNCTION
|
||||||
else if (annotated.parent is KtClassOrObject || annotated.parent is KtClassBody)
|
else -> TargetLists.T_TOP_LEVEL_FUNCTION
|
||||||
TargetLists.T_MEMBER_FUNCTION
|
}
|
||||||
else
|
|
||||||
TargetLists.T_TOP_LEVEL_FUNCTION
|
|
||||||
}
|
}
|
||||||
is KtTypeAlias -> TargetLists.T_TYPEALIAS
|
is KtTypeAlias -> TargetLists.T_TYPEALIAS
|
||||||
is KtPropertyAccessor -> if (annotated.isGetter) TargetLists.T_PROPERTY_GETTER else TargetLists.T_PROPERTY_SETTER
|
is KtPropertyAccessor -> if (annotated.isGetter) TargetLists.T_PROPERTY_GETTER else TargetLists.T_PROPERTY_SETTER
|
||||||
@@ -266,18 +262,20 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun T_MEMBER_PROPERTY(backingField: Boolean, delegate: Boolean) =
|
fun T_MEMBER_PROPERTY(backingField: Boolean, delegate: Boolean) =
|
||||||
targetList(if (backingField) MEMBER_PROPERTY_WITH_BACKING_FIELD
|
targetList(when {
|
||||||
else if (delegate) MEMBER_PROPERTY_WITH_DELEGATE
|
backingField -> MEMBER_PROPERTY_WITH_BACKING_FIELD
|
||||||
else MEMBER_PROPERTY_WITHOUT_FIELD_OR_DELEGATE,
|
delegate -> MEMBER_PROPERTY_WITH_DELEGATE
|
||||||
MEMBER_PROPERTY, PROPERTY) {
|
else -> MEMBER_PROPERTY_WITHOUT_FIELD_OR_DELEGATE
|
||||||
|
}, MEMBER_PROPERTY, PROPERTY) {
|
||||||
propertyTargets(backingField, delegate)
|
propertyTargets(backingField, delegate)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun T_TOP_LEVEL_PROPERTY(backingField: Boolean, delegate: Boolean) =
|
fun T_TOP_LEVEL_PROPERTY(backingField: Boolean, delegate: Boolean) =
|
||||||
targetList(if (backingField) TOP_LEVEL_PROPERTY_WITH_BACKING_FIELD
|
targetList(when {
|
||||||
else if (delegate) TOP_LEVEL_PROPERTY_WITH_DELEGATE
|
backingField -> TOP_LEVEL_PROPERTY_WITH_BACKING_FIELD
|
||||||
else TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE,
|
delegate -> TOP_LEVEL_PROPERTY_WITH_DELEGATE
|
||||||
TOP_LEVEL_PROPERTY, PROPERTY) {
|
else -> TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE
|
||||||
|
}, TOP_LEVEL_PROPERTY, PROPERTY) {
|
||||||
propertyTargets(backingField, delegate)
|
propertyTargets(backingField, delegate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -418,19 +418,19 @@ class DeclarationsChecker(
|
|||||||
FiniteBoundRestrictionChecker.check(aClass, classDescriptor, trace)
|
FiniteBoundRestrictionChecker.check(aClass, classDescriptor, trace)
|
||||||
NonExpansiveInheritanceRestrictionChecker.check(aClass, classDescriptor, trace)
|
NonExpansiveInheritanceRestrictionChecker.check(aClass, classDescriptor, trace)
|
||||||
|
|
||||||
if (aClass.isInterface()) {
|
when {
|
||||||
checkConstructorInInterface(aClass)
|
aClass.isInterface() -> {
|
||||||
checkMethodsOfAnyInInterface(classDescriptor)
|
checkConstructorInInterface(aClass)
|
||||||
if (aClass.isLocal && classDescriptor.containingDeclaration !is ClassDescriptor) {
|
checkMethodsOfAnyInInterface(classDescriptor)
|
||||||
trace.report(LOCAL_INTERFACE_NOT_ALLOWED.on(aClass, classDescriptor))
|
if (aClass.isLocal && classDescriptor.containingDeclaration !is ClassDescriptor) {
|
||||||
|
trace.report(LOCAL_INTERFACE_NOT_ALLOWED.on(aClass, classDescriptor))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
classDescriptor.kind == ClassKind.ANNOTATION_CLASS -> {
|
||||||
else if (classDescriptor.kind == ClassKind.ANNOTATION_CLASS) {
|
checkAnnotationClassWithBody(aClass)
|
||||||
checkAnnotationClassWithBody(aClass)
|
checkValOnAnnotationParameter(aClass)
|
||||||
checkValOnAnnotationParameter(aClass)
|
}
|
||||||
}
|
aClass is KtEnumEntry -> checkEnumEntry(aClass, classDescriptor)
|
||||||
else if (aClass is KtEnumEntry) {
|
|
||||||
checkEnumEntry(aClass, classDescriptor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,17 +692,11 @@ class DeclarationsChecker(
|
|||||||
val delegate = property.delegate
|
val delegate = property.delegate
|
||||||
val isHeader = propertyDescriptor.isHeader
|
val isHeader = propertyDescriptor.isHeader
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
if (inInterface) {
|
when {
|
||||||
trace.report(PROPERTY_INITIALIZER_IN_INTERFACE.on(initializer))
|
inInterface -> trace.report(PROPERTY_INITIALIZER_IN_INTERFACE.on(initializer))
|
||||||
}
|
isHeader -> trace.report(HEADER_PROPERTY_INITIALIZER.on(initializer))
|
||||||
else if (isHeader) {
|
!backingFieldRequired -> trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer))
|
||||||
trace.report(HEADER_PROPERTY_INITIALIZER.on(initializer))
|
property.receiverTypeReference != null -> trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer))
|
||||||
}
|
|
||||||
else if (!backingFieldRequired) {
|
|
||||||
trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer))
|
|
||||||
}
|
|
||||||
else if (property.receiverTypeReference != null) {
|
|
||||||
trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (delegate != null) {
|
else if (delegate != null) {
|
||||||
|
|||||||
@@ -69,12 +69,11 @@ open class DelegatingBindingTrace(
|
|||||||
private val bindingContext = MyBindingContext()
|
private val bindingContext = MyBindingContext()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.mutableDiagnostics = if (filter.ignoreDiagnostics)
|
this.mutableDiagnostics = when {
|
||||||
null
|
filter.ignoreDiagnostics -> null
|
||||||
else if (withParentDiagnostics)
|
withParentDiagnostics -> MutableDiagnosticsWithSuppression(bindingContext, parentContext.diagnostics)
|
||||||
MutableDiagnosticsWithSuppression(bindingContext, parentContext.diagnostics)
|
else -> MutableDiagnosticsWithSuppression(bindingContext)
|
||||||
else
|
}
|
||||||
MutableDiagnosticsWithSuppression(bindingContext)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(parentContext: BindingContext,
|
constructor(parentContext: BindingContext,
|
||||||
|
|||||||
@@ -122,14 +122,13 @@ class FunctionDescriptorResolver(
|
|||||||
assert(function.typeReference == null) {
|
assert(function.typeReference == null) {
|
||||||
"Return type must be initialized early for function: " + function.text + ", at: " + DiagnosticUtils.atLocation(function) }
|
"Return type must be initialized early for function: " + function.text + ", at: " + DiagnosticUtils.atLocation(function) }
|
||||||
|
|
||||||
val returnType = if (function.hasBlockBody()) {
|
val returnType = when {
|
||||||
builtIns.unitType
|
function.hasBlockBody() ->
|
||||||
}
|
builtIns.unitType
|
||||||
else if (function.hasBody()) {
|
function.hasBody() ->
|
||||||
descriptorResolver.inferReturnTypeFromExpressionBody(trace, scope, dataFlowInfo, function, functionDescriptor)
|
descriptorResolver.inferReturnTypeFromExpressionBody(trace, scope, dataFlowInfo, function, functionDescriptor)
|
||||||
}
|
else ->
|
||||||
else {
|
ErrorUtils.createErrorType("No type, no body")
|
||||||
ErrorUtils.createErrorType("No type, no body")
|
|
||||||
}
|
}
|
||||||
functionDescriptor.setReturnType(returnType)
|
functionDescriptor.setReturnType(returnType)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -340,14 +340,10 @@ object ModifierCheckerCore {
|
|||||||
checkCompatibility(trace, first, second, list.owner, incorrectNodes)
|
checkCompatibility(trace, first, second, list.owner, incorrectNodes)
|
||||||
}
|
}
|
||||||
if (second !in incorrectNodes) {
|
if (second !in incorrectNodes) {
|
||||||
if (!checkTarget(trace, second, actualTargets)) {
|
when {
|
||||||
incorrectNodes += second
|
!checkTarget(trace, second, actualTargets) -> incorrectNodes += second
|
||||||
}
|
!checkParent(trace, second, parentDescriptor) -> incorrectNodes += second
|
||||||
else if (!checkParent(trace, second, parentDescriptor)) {
|
!checkLanguageLevelSupport(trace, second, languageVersionSettings, actualTargets) -> incorrectNodes += second
|
||||||
incorrectNodes += second
|
|
||||||
}
|
|
||||||
else if (!checkLanguageLevelSupport(trace, second, languageVersionSettings, actualTargets)) {
|
|
||||||
incorrectNodes += second
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -568,15 +568,17 @@ class QualifiedExpressionResolver {
|
|||||||
) {
|
) {
|
||||||
if (descriptors.size > 1) {
|
if (descriptors.size > 1) {
|
||||||
val visibleDescriptors = descriptors.filter { isVisible(it, shouldBeVisibleFrom, position) }
|
val visibleDescriptors = descriptors.filter { isVisible(it, shouldBeVisibleFrom, position) }
|
||||||
if (visibleDescriptors.isEmpty()) {
|
when {
|
||||||
val descriptor = descriptors.first() as DeclarationDescriptorWithVisibility
|
visibleDescriptors.isEmpty() -> {
|
||||||
trace.report(Errors.INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.visibility, descriptor))
|
val descriptor = descriptors.first() as DeclarationDescriptorWithVisibility
|
||||||
}
|
trace.report(Errors.INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.visibility, descriptor))
|
||||||
else if (visibleDescriptors.size > 1) {
|
}
|
||||||
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, visibleDescriptors)
|
visibleDescriptors.size > 1 -> {
|
||||||
}
|
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, visibleDescriptors)
|
||||||
else {
|
}
|
||||||
storeResult(trace, referenceExpression, visibleDescriptors.single(), null, position, isQualifier)
|
else -> {
|
||||||
|
storeResult(trace, referenceExpression, visibleDescriptors.single(), null, position, isQualifier)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+15
-13
@@ -155,21 +155,23 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
|||||||
|
|
||||||
val varDescriptor: CallableDescriptor?
|
val varDescriptor: CallableDescriptor?
|
||||||
val receiverExpression: KtExpression?
|
val receiverExpression: KtExpression?
|
||||||
if (receiver is ExpressionReceiver) {
|
when (receiver) {
|
||||||
receiverExpression = receiver.expression
|
is ExpressionReceiver -> {
|
||||||
varDescriptor = getCalleeDescriptor(context, receiverExpression, true)
|
receiverExpression = receiver.expression
|
||||||
}
|
varDescriptor = getCalleeDescriptor(context, receiverExpression, true)
|
||||||
else if (receiver is ExtensionReceiver) {
|
}
|
||||||
val extension = receiver.declarationDescriptor
|
is ExtensionReceiver -> {
|
||||||
|
val extension = receiver.declarationDescriptor
|
||||||
|
|
||||||
varDescriptor = extension.extensionReceiverParameter
|
varDescriptor = extension.extensionReceiverParameter
|
||||||
assert(varDescriptor != null) { "Extension should have receiverParameterDescriptor: " + extension }
|
assert(varDescriptor != null) { "Extension should have receiverParameterDescriptor: " + extension }
|
||||||
|
|
||||||
receiverExpression = expression
|
receiverExpression = expression
|
||||||
}
|
}
|
||||||
else {
|
else -> {
|
||||||
varDescriptor = null
|
varDescriptor = null
|
||||||
receiverExpression = null
|
receiverExpression = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inlinableParameters.contains(varDescriptor)) {
|
if (inlinableParameters.contains(varDescriptor)) {
|
||||||
|
|||||||
@@ -50,18 +50,18 @@ fun ResolvedCall<*>.hasThisOrNoDispatchReceiver(
|
|||||||
if (resultingDescriptor.dispatchReceiverParameter == null || dispatchReceiverValue == null) return true
|
if (resultingDescriptor.dispatchReceiverParameter == null || dispatchReceiverValue == null) return true
|
||||||
|
|
||||||
var dispatchReceiverDescriptor: DeclarationDescriptor? = null
|
var dispatchReceiverDescriptor: DeclarationDescriptor? = null
|
||||||
if (dispatchReceiverValue is ImplicitReceiver) {
|
when (dispatchReceiverValue) {
|
||||||
// foo() -- implicit receiver
|
is ImplicitReceiver -> // foo() -- implicit receiver
|
||||||
dispatchReceiverDescriptor = dispatchReceiverValue.declarationDescriptor
|
dispatchReceiverDescriptor = dispatchReceiverValue.declarationDescriptor
|
||||||
}
|
is ClassValueReceiver -> {
|
||||||
else if (dispatchReceiverValue is ClassValueReceiver) {
|
dispatchReceiverDescriptor = dispatchReceiverValue.classQualifier.descriptor
|
||||||
dispatchReceiverDescriptor = dispatchReceiverValue.classQualifier.descriptor
|
}
|
||||||
}
|
is ExpressionReceiver -> {
|
||||||
else if (dispatchReceiverValue is ExpressionReceiver) {
|
val expression = KtPsiUtil.deparenthesize(dispatchReceiverValue.expression)
|
||||||
val expression = KtPsiUtil.deparenthesize(dispatchReceiverValue.expression)
|
if (expression is KtThisExpression) {
|
||||||
if (expression is KtThisExpression) {
|
// this.foo() -- explicit receiver
|
||||||
// this.foo() -- explicit receiver
|
dispatchReceiverDescriptor = context.get(BindingContext.REFERENCE_TARGET, expression.instanceReference)
|
||||||
dispatchReceiverDescriptor = context.get(BindingContext.REFERENCE_TARGET, expression.instanceReference)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -283,9 +283,11 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
private fun Set<KotlinType>.containsNothing() = any { KotlinBuiltIns.isNothing(it) }
|
private fun Set<KotlinType>.containsNothing() = any { KotlinBuiltIns.isNothing(it) }
|
||||||
|
|
||||||
private fun Set<KotlinType>.intersect(other: Set<KotlinType>) =
|
private fun Set<KotlinType>.intersect(other: Set<KotlinType>) =
|
||||||
if (other.containsNothing()) this
|
when {
|
||||||
else if (this.containsNothing()) other
|
other.containsNothing() -> this
|
||||||
else Sets.intersection(this, other)
|
this.containsNothing() -> other
|
||||||
|
else -> Sets.intersection(this, other)
|
||||||
|
}
|
||||||
|
|
||||||
override fun or(other: DataFlowInfo): DataFlowInfo {
|
override fun or(other: DataFlowInfo): DataFlowInfo {
|
||||||
if (other === DataFlowInfo.EMPTY) return DataFlowInfo.EMPTY
|
if (other === DataFlowInfo.EMPTY) return DataFlowInfo.EMPTY
|
||||||
|
|||||||
+4
-8
@@ -145,14 +145,10 @@ abstract class KotlinSuppressCache {
|
|||||||
var suppressor: Suppressor? = suppressors[annotated]
|
var suppressor: Suppressor? = suppressors[annotated]
|
||||||
if (suppressor == null) {
|
if (suppressor == null) {
|
||||||
val strings = getSuppressingStrings(annotated)
|
val strings = getSuppressingStrings(annotated)
|
||||||
if (strings.isEmpty()) {
|
suppressor = when {
|
||||||
suppressor = EmptySuppressor(annotated)
|
strings.isEmpty() -> EmptySuppressor(annotated)
|
||||||
}
|
strings.size == 1 -> SingularSuppressor(annotated, strings.iterator().next())
|
||||||
else if (strings.size == 1) {
|
else -> MultiSuppressor(annotated, strings)
|
||||||
suppressor = SingularSuppressor(annotated, strings.iterator().next())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
suppressor = MultiSuppressor(annotated, strings)
|
|
||||||
}
|
}
|
||||||
suppressors.put(annotated, suppressor)
|
suppressors.put(annotated, suppressor)
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-33
@@ -169,46 +169,48 @@ protected constructor(
|
|||||||
val declarations = declarationProvider.getDeclarations(kindFilter, nameFilter)
|
val declarations = declarationProvider.getDeclarations(kindFilter, nameFilter)
|
||||||
val result = LinkedHashSet<DeclarationDescriptor>(declarations.size)
|
val result = LinkedHashSet<DeclarationDescriptor>(declarations.size)
|
||||||
for (declaration in declarations) {
|
for (declaration in declarations) {
|
||||||
if (declaration is KtClassOrObject) {
|
when (declaration) {
|
||||||
val name = declaration.nameAsSafeName
|
is KtClassOrObject -> {
|
||||||
if (nameFilter(name)) {
|
val name = declaration.nameAsSafeName
|
||||||
result.addAll(classDescriptors(name))
|
if (nameFilter(name)) {
|
||||||
|
result.addAll(classDescriptors(name))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtFunction -> {
|
||||||
else if (declaration is KtFunction) {
|
val name = declaration.nameAsSafeName
|
||||||
val name = declaration.nameAsSafeName
|
if (nameFilter(name)) {
|
||||||
if (nameFilter(name)) {
|
result.addAll(getContributedFunctions(name, location))
|
||||||
result.addAll(getContributedFunctions(name, location))
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtProperty -> {
|
||||||
else if (declaration is KtProperty) {
|
val name = declaration.nameAsSafeName
|
||||||
val name = declaration.nameAsSafeName
|
if (nameFilter(name)) {
|
||||||
if (nameFilter(name)) {
|
result.addAll(getContributedVariables(name, location))
|
||||||
result.addAll(getContributedVariables(name, location))
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtParameter -> {
|
||||||
else if (declaration is KtParameter) {
|
val name = declaration.nameAsSafeName
|
||||||
val name = declaration.nameAsSafeName
|
if (nameFilter(name)) {
|
||||||
if (nameFilter(name)) {
|
result.addAll(getContributedVariables(name, location))
|
||||||
result.addAll(getContributedVariables(name, location))
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtTypeAlias -> {
|
||||||
else if (declaration is KtTypeAlias) {
|
val name = declaration.nameAsSafeName
|
||||||
val name = declaration.nameAsSafeName
|
if (nameFilter(name)) {
|
||||||
if (nameFilter(name)) {
|
result.addAll(getContributedTypeAliasDescriptors(name, location))
|
||||||
result.addAll(getContributedTypeAliasDescriptors(name, location))
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtScript -> {
|
||||||
else if (declaration is KtScript) {
|
val name = declaration.nameAsSafeName
|
||||||
val name = declaration.nameAsSafeName
|
if (nameFilter(name)) {
|
||||||
if (nameFilter(name)) {
|
result.addAll(classDescriptors(name))
|
||||||
result.addAll(classDescriptors(name))
|
}
|
||||||
}
|
}
|
||||||
|
is KtDestructuringDeclaration -> {
|
||||||
|
// MultiDeclarations are not supported on global level
|
||||||
|
}
|
||||||
|
else -> throw IllegalArgumentException("Unsupported declaration kind: " + declaration)
|
||||||
}
|
}
|
||||||
else if (declaration is KtDestructuringDeclaration) {
|
|
||||||
// MultiDeclarations are not supported on global level
|
|
||||||
}
|
|
||||||
else throw IllegalArgumentException("Unsupported declaration kind: " + declaration)
|
|
||||||
}
|
}
|
||||||
return result.toList()
|
return result.toList()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,44 +137,45 @@ object LabelResolver {
|
|||||||
|
|
||||||
val declarationsByLabel = context.scope.getDeclarationsByLabel(labelName)
|
val declarationsByLabel = context.scope.getDeclarationsByLabel(labelName)
|
||||||
val size = declarationsByLabel.size
|
val size = declarationsByLabel.size
|
||||||
if (size == 1) {
|
when (size) {
|
||||||
val declarationDescriptor = declarationsByLabel.single()
|
1 -> {
|
||||||
val thisReceiver = when (declarationDescriptor) {
|
val declarationDescriptor = declarationsByLabel.single()
|
||||||
is ClassDescriptor -> declarationDescriptor.thisAsReceiverParameter
|
val thisReceiver = when (declarationDescriptor) {
|
||||||
is FunctionDescriptor -> declarationDescriptor.extensionReceiverParameter
|
is ClassDescriptor -> declarationDescriptor.thisAsReceiverParameter
|
||||||
is PropertyDescriptor -> declarationDescriptor.extensionReceiverParameter
|
is FunctionDescriptor -> declarationDescriptor.extensionReceiverParameter
|
||||||
else -> throw UnsupportedOperationException("Unsupported descriptor: " + declarationDescriptor) // TODO
|
is PropertyDescriptor -> declarationDescriptor.extensionReceiverParameter
|
||||||
}
|
else -> throw UnsupportedOperationException("Unsupported descriptor: " + declarationDescriptor) // TODO
|
||||||
|
|
||||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(declarationDescriptor) ?: error("No PSI element for descriptor: " + declarationDescriptor)
|
|
||||||
context.trace.record(LABEL_TARGET, targetLabel, element)
|
|
||||||
context.trace.record(REFERENCE_TARGET, referenceExpression, declarationDescriptor)
|
|
||||||
|
|
||||||
if (declarationDescriptor is ClassDescriptor) {
|
|
||||||
if (!DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, targetLabel, declarationDescriptor)) {
|
|
||||||
return LabeledReceiverResolutionResult.labelResolutionFailed()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return LabeledReceiverResolutionResult.labelResolutionSuccess(thisReceiver)
|
val element = DescriptorToSourceUtils.descriptorToDeclaration(declarationDescriptor)
|
||||||
}
|
?: error("No PSI element for descriptor: " + declarationDescriptor)
|
||||||
else if (size == 0) {
|
context.trace.record(LABEL_TARGET, targetLabel, element)
|
||||||
val element = resolveNamedLabel(labelName, targetLabel, context.trace)
|
context.trace.record(REFERENCE_TARGET, referenceExpression, declarationDescriptor)
|
||||||
val declarationDescriptor = context.trace.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element]
|
|
||||||
if (declarationDescriptor is FunctionDescriptor) {
|
if (declarationDescriptor is ClassDescriptor) {
|
||||||
val thisReceiver = declarationDescriptor.extensionReceiverParameter
|
if (!DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, targetLabel, declarationDescriptor)) {
|
||||||
if (thisReceiver != null) {
|
return LabeledReceiverResolutionResult.labelResolutionFailed()
|
||||||
context.trace.record(LABEL_TARGET, targetLabel, element)
|
}
|
||||||
context.trace.record(REFERENCE_TARGET, referenceExpression, declarationDescriptor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return LabeledReceiverResolutionResult.labelResolutionSuccess(thisReceiver)
|
return LabeledReceiverResolutionResult.labelResolutionSuccess(thisReceiver)
|
||||||
}
|
}
|
||||||
else {
|
0 -> {
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel, targetLabel))
|
val element = resolveNamedLabel(labelName, targetLabel, context.trace)
|
||||||
|
val declarationDescriptor = context.trace.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element]
|
||||||
|
if (declarationDescriptor is FunctionDescriptor) {
|
||||||
|
val thisReceiver = declarationDescriptor.extensionReceiverParameter
|
||||||
|
if (thisReceiver != null) {
|
||||||
|
context.trace.record(LABEL_TARGET, targetLabel, element)
|
||||||
|
context.trace.record(REFERENCE_TARGET, referenceExpression, declarationDescriptor)
|
||||||
|
}
|
||||||
|
return LabeledReceiverResolutionResult.labelResolutionSuccess(thisReceiver)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel, targetLabel))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else -> BindingContextUtils.reportAmbiguousLabel(context.trace, targetLabel, declarationsByLabel)
|
||||||
else {
|
|
||||||
BindingContextUtils.reportAmbiguousLabel(context.trace, targetLabel, declarationsByLabel)
|
|
||||||
}
|
}
|
||||||
return LabeledReceiverResolutionResult.labelResolutionFailed()
|
return LabeledReceiverResolutionResult.labelResolutionFailed()
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-7
@@ -38,9 +38,11 @@ object SenselessComparisonChecker {
|
|||||||
getNullability: (DataFlowValue) -> Nullability
|
getNullability: (DataFlowValue) -> Nullability
|
||||||
) {
|
) {
|
||||||
val expr =
|
val expr =
|
||||||
if (KtPsiUtil.isNullConstant(left)) right
|
when {
|
||||||
else if (KtPsiUtil.isNullConstant(right)) left
|
KtPsiUtil.isNullConstant(left) -> right
|
||||||
else return
|
KtPsiUtil.isNullConstant(right) -> left
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
val type = getType(expr)
|
val type = getType(expr)
|
||||||
if (type == null || type.isError) return
|
if (type == null || type.isError) return
|
||||||
@@ -52,10 +54,12 @@ object SenselessComparisonChecker {
|
|||||||
val nullability = getNullability(value)
|
val nullability = getNullability(value)
|
||||||
|
|
||||||
val expressionIsAlways =
|
val expressionIsAlways =
|
||||||
if (nullability == Nullability.NULL) equality
|
when (nullability) {
|
||||||
else if (nullability == Nullability.NOT_NULL) !equality
|
Nullability.NULL -> equality
|
||||||
else if (nullability == Nullability.IMPOSSIBLE) false
|
Nullability.NOT_NULL -> !equality
|
||||||
else return
|
Nullability.IMPOSSIBLE -> false
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
context.trace.report(Errors.SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways))
|
context.trace.report(Errors.SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways))
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-22
@@ -632,22 +632,20 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
val stackElement = data.peek()
|
val stackElement = data.peek()
|
||||||
|
|
||||||
if (stackElement is TryInfo) {
|
when (stackElement) {
|
||||||
//noinspection ConstantConditions
|
is TryInfo -> //noinspection ConstantConditions
|
||||||
genFinallyBlockOrGoto(stackElement, null, afterBreakContinueLabel, data)
|
genFinallyBlockOrGoto(stackElement, null, afterBreakContinueLabel, data)
|
||||||
}
|
is LoopInfo -> {
|
||||||
else if (stackElement is LoopInfo) {
|
val loop = expression.loop
|
||||||
val loop = expression.loop
|
//noinspection ConstantConditions
|
||||||
//noinspection ConstantConditions
|
if (loop == stackElement.loop) {
|
||||||
if (loop == stackElement.loop) {
|
val label = if (expression is IrBreak) stackElement.breakLabel else stackElement.continueLabel
|
||||||
val label = if (expression is IrBreak) stackElement.breakLabel else stackElement.continueLabel
|
mv.fixStackAndJump(label)
|
||||||
mv.fixStackAndJump(label)
|
mv.mark(afterBreakContinueLabel)
|
||||||
mv.mark(afterBreakContinueLabel)
|
return
|
||||||
return
|
}
|
||||||
}
|
}
|
||||||
}
|
else -> throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
|
||||||
else {
|
|
||||||
throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.pop()
|
data.pop()
|
||||||
@@ -829,14 +827,12 @@ class ExpressionCodegen(
|
|||||||
private fun doFinallyOnReturn(afterReturnLabel: Label, data: BlockInfo) {
|
private fun doFinallyOnReturn(afterReturnLabel: Label, data: BlockInfo) {
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
val stackElement = data.peek()
|
val stackElement = data.peek()
|
||||||
if (stackElement is TryInfo) {
|
when (stackElement) {
|
||||||
genFinallyBlockOrGoto(stackElement, null, afterReturnLabel, data)
|
is TryInfo -> genFinallyBlockOrGoto(stackElement, null, afterReturnLabel, data)
|
||||||
}
|
is LoopInfo -> {
|
||||||
else if (stackElement is LoopInfo) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else -> throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
|
||||||
throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.pop()
|
data.pop()
|
||||||
|
|||||||
+12
-10
@@ -163,16 +163,18 @@ class StatementGenerator(
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val label = expression.getTargetLabel()
|
val label = expression.getTargetLabel()
|
||||||
if (label != null) {
|
when {
|
||||||
val labelTarget = getOrFail(BindingContext.LABEL_TARGET, label)
|
label != null -> {
|
||||||
val labelTargetDescriptor = getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, labelTarget)
|
val labelTarget = getOrFail(BindingContext.LABEL_TARGET, label)
|
||||||
labelTargetDescriptor as CallableDescriptor
|
val labelTargetDescriptor = getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, labelTarget)
|
||||||
}
|
labelTargetDescriptor as CallableDescriptor
|
||||||
else if (ExpressionTypingUtils.isFunctionLiteral(scopeOwner)) {
|
}
|
||||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(scopeOwner, true).first
|
ExpressionTypingUtils.isFunctionLiteral(scopeOwner) -> {
|
||||||
}
|
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(scopeOwner, true).first
|
||||||
else {
|
}
|
||||||
scopeOwnerAsCallable()
|
else -> {
|
||||||
|
scopeOwnerAsCallable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-18
@@ -168,25 +168,27 @@ private fun <C : Candidate> createSimpleProcessor(
|
|||||||
classValueReceiver: Boolean,
|
classValueReceiver: Boolean,
|
||||||
collectCandidates: CandidatesCollector
|
collectCandidates: CandidatesCollector
|
||||||
) : ScopeTowerProcessor<C> {
|
) : ScopeTowerProcessor<C> {
|
||||||
if (explicitReceiver is ReceiverValueWithSmartCastInfo) {
|
return when (explicitReceiver) {
|
||||||
return ExplicitReceiverScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
|
is ReceiverValueWithSmartCastInfo -> {
|
||||||
}
|
ExplicitReceiverScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
|
||||||
else if (explicitReceiver is QualifierReceiver) {
|
}
|
||||||
val qualifierProcessor = QualifierScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
|
is QualifierReceiver -> {
|
||||||
if (!classValueReceiver) return qualifierProcessor
|
val qualifierProcessor = QualifierScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
|
||||||
|
if (!classValueReceiver) return qualifierProcessor
|
||||||
// todo enum entry, object.
|
|
||||||
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return qualifierProcessor
|
// todo enum entry, object.
|
||||||
return CompositeScopeTowerProcessor(
|
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return qualifierProcessor
|
||||||
qualifierProcessor,
|
CompositeScopeTowerProcessor(
|
||||||
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
|
qualifierProcessor,
|
||||||
)
|
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
|
||||||
}
|
)
|
||||||
else {
|
}
|
||||||
assert(explicitReceiver == null) {
|
else -> {
|
||||||
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!::class.java.simpleName})"
|
assert(explicitReceiver == null) {
|
||||||
|
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!::class.java.simpleName})"
|
||||||
|
}
|
||||||
|
NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
|
||||||
}
|
}
|
||||||
return NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -252,19 +252,21 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
|
|||||||
anySupertype(baseType, { false }) {
|
anySupertype(baseType, { false }) {
|
||||||
val current = captureFromArguments(it, CaptureStatus.FOR_SUBTYPING)
|
val current = captureFromArguments(it, CaptureStatus.FOR_SUBTYPING)
|
||||||
|
|
||||||
if (areEqualTypeConstructors(current.constructor, constructor)) {
|
when {
|
||||||
if (result == null) {
|
areEqualTypeConstructors(current.constructor, constructor) -> {
|
||||||
result = SmartList()
|
if (result == null) {
|
||||||
}
|
result = SmartList()
|
||||||
result!!.add(current)
|
}
|
||||||
|
result!!.add(current)
|
||||||
|
|
||||||
SupertypesPolicy.None
|
SupertypesPolicy.None
|
||||||
}
|
}
|
||||||
else if (current.arguments.isEmpty()) {
|
current.arguments.isEmpty() -> {
|
||||||
SupertypesPolicy.LowerIfFlexible
|
SupertypesPolicy.LowerIfFlexible
|
||||||
}
|
}
|
||||||
else {
|
else -> {
|
||||||
SupertypesPolicy.LowerIfFlexibleWithCustomSubstitutor(TypeConstructorSubstitution.create(current).buildSubstitutor())
|
SupertypesPolicy.LowerIfFlexibleWithCustomSubstitutor(TypeConstructorSubstitution.create(current).buildSubstitutor())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,29 +208,33 @@ internal object RuntimeTypeMapper {
|
|||||||
|
|
||||||
fun mapPropertySignature(possiblyOverriddenProperty: PropertyDescriptor): JvmPropertySignature {
|
fun mapPropertySignature(possiblyOverriddenProperty: PropertyDescriptor): JvmPropertySignature {
|
||||||
val property = DescriptorUtils.unwrapFakeOverride(possiblyOverriddenProperty).original
|
val property = DescriptorUtils.unwrapFakeOverride(possiblyOverriddenProperty).original
|
||||||
if (property is DeserializedPropertyDescriptor) {
|
return when (property) {
|
||||||
val proto = property.proto
|
is DeserializedPropertyDescriptor -> {
|
||||||
if (!proto.hasExtension(JvmProtoBuf.propertySignature)) {
|
val proto = property.proto
|
||||||
// If this property has no JVM signature, it must be from built-ins
|
if (!proto.hasExtension(JvmProtoBuf.propertySignature)) {
|
||||||
throw KotlinReflectionInternalError("Reflection on built-in Kotlin types is not yet fully supported. " +
|
// If this property has no JVM signature, it must be from built-ins
|
||||||
"No metadata found for $property")
|
throw KotlinReflectionInternalError("Reflection on built-in Kotlin types is not yet fully supported. " +
|
||||||
}
|
"No metadata found for $property")
|
||||||
return JvmPropertySignature.KotlinProperty(
|
}
|
||||||
property, proto, proto.getExtension(JvmProtoBuf.propertySignature), property.nameResolver, property.typeTable
|
JvmPropertySignature.KotlinProperty(
|
||||||
)
|
property, proto, proto.getExtension(JvmProtoBuf.propertySignature), property.nameResolver, property.typeTable
|
||||||
}
|
|
||||||
else if (property is JavaPropertyDescriptor) {
|
|
||||||
val element = (property.source as? JavaSourceElement)?.javaElement
|
|
||||||
when (element) {
|
|
||||||
is ReflectJavaField -> return JvmPropertySignature.JavaField(element.member)
|
|
||||||
is ReflectJavaMethod -> return JvmPropertySignature.JavaMethodProperty(
|
|
||||||
element.member,
|
|
||||||
((property.setter?.source as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member
|
|
||||||
)
|
)
|
||||||
else -> throw KotlinReflectionInternalError("Incorrect resolution sequence for Java field $property (source = $element)")
|
}
|
||||||
|
is JavaPropertyDescriptor -> {
|
||||||
|
val element = (property.source as? JavaSourceElement)?.javaElement
|
||||||
|
when (element) {
|
||||||
|
is ReflectJavaField -> JvmPropertySignature.JavaField(element.member)
|
||||||
|
is ReflectJavaMethod -> JvmPropertySignature.JavaMethodProperty(
|
||||||
|
element.member,
|
||||||
|
((property.setter?.source as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member
|
||||||
|
)
|
||||||
|
else -> throw KotlinReflectionInternalError("Incorrect resolution sequence for Java field $property (source = $element)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mapIntrinsicFunctionSignature(function: FunctionDescriptor): JvmFunctionSignature? {
|
private fun mapIntrinsicFunctionSignature(function: FunctionDescriptor): JvmFunctionSignature? {
|
||||||
|
|||||||
@@ -181,13 +181,10 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
|||||||
|
|
||||||
CHECKCAST -> {
|
CHECKCAST -> {
|
||||||
val targetType = Type.getObjectType((insn as TypeInsnNode).desc)
|
val targetType = Type.getObjectType((insn as TypeInsnNode).desc)
|
||||||
if (value == NULL_VALUE) {
|
when {
|
||||||
NULL_VALUE
|
value == NULL_VALUE -> NULL_VALUE
|
||||||
} else if (eval.isInstanceOf(value, targetType)) {
|
eval.isInstanceOf(value, targetType) -> ObjectValue(value.obj(), targetType)
|
||||||
ObjectValue(value.obj(), targetType)
|
else -> throwEvalException(ClassCastException("${value.asmType.className} cannot be cast to ${targetType.className}"))
|
||||||
}
|
|
||||||
else {
|
|
||||||
throwEvalException(ClassCastException("${value.asmType.className} cannot be cast to ${targetType.className}"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -212,14 +212,13 @@ class OptimizedImportsBuilder(
|
|||||||
val explicitImportPath = ImportPath(fqName, false)
|
val explicitImportPath = ImportPath(fqName, false)
|
||||||
val starImportPath = ImportPath(fqName.parent(), true)
|
val starImportPath = ImportPath(fqName.parent(), true)
|
||||||
val importPaths = file.importDirectives.map { it.importPath }
|
val importPaths = file.importDirectives.map { it.importPath }
|
||||||
if (explicitImportPath in importPaths) {
|
when {
|
||||||
importRules.add(ImportRule.Add(explicitImportPath))
|
explicitImportPath in importPaths ->
|
||||||
}
|
importRules.add(ImportRule.Add(explicitImportPath))
|
||||||
else if (starImportPath in importPaths) {
|
starImportPath in importPaths ->
|
||||||
importRules.add(ImportRule.Add(starImportPath))
|
importRules.add(ImportRule.Add(starImportPath))
|
||||||
}
|
else -> // there is no import for this descriptor in the original import list, so do not allow to import it by star-import
|
||||||
else { // there is no import for this descriptor in the original import list, so do not allow to import it by star-import
|
importRules.add(ImportRule.DoNotAdd(starImportPath))
|
||||||
importRules.add(ImportRule.DoNotAdd(starImportPath))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,14 +276,10 @@ class OptimizedImportsBuilder(
|
|||||||
val iterator1 = tower1.iterator()
|
val iterator1 = tower1.iterator()
|
||||||
val iterator2 = tower2.iterator()
|
val iterator2 = tower2.iterator()
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!iterator1.hasNext()) {
|
when {
|
||||||
return !iterator2.hasNext()
|
!iterator1.hasNext() -> return !iterator2.hasNext()
|
||||||
}
|
!iterator2.hasNext() -> return false
|
||||||
else if (!iterator2.hasNext()) {
|
else -> if (!areTargetsEqual(iterator1.next(), iterator2.next())) return false
|
||||||
return false
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!areTargetsEqual(iterator1.next(), iterator2.next())) return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,18 +271,18 @@ class PartialBodyResolveFilter(
|
|||||||
val left = condition.left ?: return emptyResult
|
val left = condition.left ?: return emptyResult
|
||||||
val right = condition.right ?: return emptyResult
|
val right = condition.right ?: return emptyResult
|
||||||
|
|
||||||
fun smartCastInEq(): Pair<Set<SmartCastName>, Set<SmartCastName>> {
|
fun smartCastInEq(): Pair<Set<SmartCastName>, Set<SmartCastName>> = when {
|
||||||
if (left.isNullLiteral()) {
|
left.isNullLiteral() -> {
|
||||||
return Pair(setOf(), right.smartCastExpressionName().singletonOrEmptySet())
|
Pair(setOf(), right.smartCastExpressionName().singletonOrEmptySet())
|
||||||
}
|
}
|
||||||
else if (right.isNullLiteral()) {
|
right.isNullLiteral() -> {
|
||||||
return Pair(setOf(), left.smartCastExpressionName().singletonOrEmptySet())
|
Pair(setOf(), left.smartCastExpressionName().singletonOrEmptySet())
|
||||||
}
|
}
|
||||||
else {
|
else -> {
|
||||||
val leftName = left.smartCastExpressionName()
|
val leftName = left.smartCastExpressionName()
|
||||||
val rightName = right.smartCastExpressionName()
|
val rightName = right.smartCastExpressionName()
|
||||||
val names = listOfNotNull(leftName, rightName).toSet()
|
val names = listOfNotNull(leftName, rightName).toSet()
|
||||||
return Pair(names, setOf())
|
Pair(names, setOf())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-18
@@ -217,26 +217,26 @@ object IDELightClassContexts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (declaration in file.declarations) {
|
for (declaration in file.declarations) {
|
||||||
if (declaration is KtFunction) {
|
when (declaration) {
|
||||||
val name = declaration.nameAsSafeName
|
is KtFunction -> {
|
||||||
val functions = packageDescriptor.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE)
|
val name = declaration.nameAsSafeName
|
||||||
for (descriptor in functions) {
|
val functions = packageDescriptor.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE)
|
||||||
ForceResolveUtil.forceResolveAllContents(descriptor)
|
for (descriptor in functions) {
|
||||||
|
ForceResolveUtil.forceResolveAllContents(descriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtProperty -> {
|
||||||
else if (declaration is KtProperty) {
|
val name = declaration.nameAsSafeName
|
||||||
val name = declaration.nameAsSafeName
|
val properties = packageDescriptor.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
|
||||||
val properties = packageDescriptor.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
|
for (descriptor in properties) {
|
||||||
for (descriptor in properties) {
|
ForceResolveUtil.forceResolveAllContents(descriptor)
|
||||||
ForceResolveUtil.forceResolveAllContents(descriptor)
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtClassOrObject, is KtTypeAlias, is KtDestructuringDeclaration -> {
|
||||||
else if (declaration is KtClassOrObject || declaration is KtTypeAlias || declaration is KtDestructuringDeclaration) {
|
// Do nothing: we are not interested in classes or type aliases,
|
||||||
// Do nothing: we are not interested in classes or type aliases,
|
// and all destructuring declarations are erroneous at top level
|
||||||
// and all destructuring declarations are erroneous at top level
|
}
|
||||||
}
|
else -> LOG.error("Unsupported declaration kind: " + declaration + " in file " + file.name + "\n" + file.text)
|
||||||
else {
|
|
||||||
LOG.error("Unsupported declaration kind: " + declaration + " in file " + file.name + "\n" + file.text)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,11 +101,18 @@ object UsageTypeUtils {
|
|||||||
CLASS_CAST_TO
|
CLASS_CAST_TO
|
||||||
|
|
||||||
with(refExpr.getNonStrictParentOfType<KtDotQualifiedExpression>()) {
|
with(refExpr.getNonStrictParentOfType<KtDotQualifiedExpression>()) {
|
||||||
if (this == null) false
|
when {
|
||||||
else if (receiverExpression == refExpr) true
|
this == null -> {
|
||||||
else
|
false
|
||||||
selectorExpression == refExpr
|
}
|
||||||
&& getParentOfTypeAndBranch<KtDotQualifiedExpression>(strict = true) { receiverExpression } != null
|
receiverExpression == refExpr -> {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
selectorExpression == refExpr
|
||||||
|
&& getParentOfTypeAndBranch<KtDotQualifiedExpression>(strict = true) { receiverExpression } != null
|
||||||
|
}
|
||||||
|
}
|
||||||
} ->
|
} ->
|
||||||
CLASS_OBJECT_ACCESS
|
CLASS_OBJECT_ACCESS
|
||||||
|
|
||||||
|
|||||||
+5
-6
@@ -49,12 +49,11 @@ object CommonLibraryDetectionUtil {
|
|||||||
|
|
||||||
var platform: TargetPlatform? = null
|
var platform: TargetPlatform? = null
|
||||||
VfsUtilCore.processFilesRecursively(root) { file ->
|
VfsUtilCore.processFilesRecursively(root) { file ->
|
||||||
if (file.fileType == JavaClassFileType.INSTANCE)
|
when {
|
||||||
platform = JvmPlatform
|
file.fileType == JavaClassFileType.INSTANCE -> platform = JvmPlatform
|
||||||
else if (isKotlinMetadataFile(file))
|
isKotlinMetadataFile(file) -> platform = TargetPlatform.Default
|
||||||
platform = TargetPlatform.Default
|
KotlinJavaScriptLibraryDetectionUtil.isJsFileWithMetadata(file) -> platform = JsPlatform
|
||||||
else if (KotlinJavaScriptLibraryDetectionUtil.isJsFileWithMetadata(file))
|
}
|
||||||
platform = JsPlatform
|
|
||||||
|
|
||||||
platform == null
|
platform == null
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -129,16 +129,12 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
val args = entry.valueArgumentList
|
val args = entry.valueArgumentList
|
||||||
val psiFactory = KtPsiFactory(entry)
|
val psiFactory = KtPsiFactory(entry)
|
||||||
val newArgList = psiFactory.createCallArguments("($id)")
|
val newArgList = psiFactory.createCallArguments("($id)")
|
||||||
if (args == null) {
|
when {
|
||||||
// new argument list
|
args == null -> // new argument list
|
||||||
entry.addAfter(newArgList, entry.lastChild)
|
entry.addAfter(newArgList, entry.lastChild)
|
||||||
}
|
args.arguments.isEmpty() -> // replace '()' with a new argument list
|
||||||
else if (args.arguments.isEmpty()) {
|
args.replace(newArgList)
|
||||||
// replace '()' with a new argument list
|
else -> args.addArgument(newArgList.arguments[0])
|
||||||
args.replace(newArgList)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args.addArgument(newArgList.arguments[0])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,14 +151,10 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName:
|
|||||||
val file = ref.containingKtFile
|
val file = ref.containingKtFile
|
||||||
var result: Result = Result.NothingFound
|
var result: Result = Result.NothingFound
|
||||||
val filePackage = file.packageFqName.asString()
|
val filePackage = file.packageFqName.asString()
|
||||||
if (filePackage == targetPackage) {
|
when (filePackage) {
|
||||||
result = result.changeTo(Result.Found)
|
targetPackage -> result = result.changeTo(Result.Found)
|
||||||
}
|
in conflictingPackages -> result = result.changeTo(Result.FoundOther)
|
||||||
else if (filePackage in conflictingPackages) {
|
in packagesWithTypeAliases -> return UNSURE
|
||||||
result = result.changeTo(Result.FoundOther)
|
|
||||||
}
|
|
||||||
else if (filePackage in packagesWithTypeAliases) {
|
|
||||||
return UNSURE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (importPath in file.getDefaultImports()) {
|
for (importPath in file.getDefaultImports()) {
|
||||||
@@ -202,14 +198,10 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (qName?.asString() == targetPackage) {
|
when {
|
||||||
return result.changeTo(Result.Found)
|
qName?.asString() == targetPackage -> return result.changeTo(Result.Found)
|
||||||
}
|
qName?.asString() in conflictingPackages -> return result.changeTo(Result.FoundOther)
|
||||||
else if (qName?.asString() in conflictingPackages) {
|
qName?.asString() in packagesWithTypeAliases -> return Result.Ambiguity
|
||||||
return result.changeTo(Result.FoundOther)
|
|
||||||
}
|
|
||||||
else if (qName?.asString() in packagesWithTypeAliases) {
|
|
||||||
return Result.Ambiguity
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
+5
-6
@@ -276,12 +276,11 @@ class BasicLookupElementFactory(
|
|||||||
appendTailText(" for $receiverPresentation")
|
appendTailText(" for $receiverPresentation")
|
||||||
|
|
||||||
val container = descriptor.containingDeclaration
|
val container = descriptor.containingDeclaration
|
||||||
val containerPresentation = if (container is ClassDescriptor)
|
val containerPresentation = when (container) {
|
||||||
DescriptorUtils.getFqNameFromTopLevelClass(container).toString()
|
is ClassDescriptor -> DescriptorUtils.getFqNameFromTopLevelClass(container).toString()
|
||||||
else if (container is PackageFragmentDescriptor)
|
is PackageFragmentDescriptor -> container.fqName.toString()
|
||||||
container.fqName.toString()
|
else -> null
|
||||||
else
|
}
|
||||||
null
|
|
||||||
if (containerPresentation != null) {
|
if (containerPresentation != null) {
|
||||||
appendTailText(" in $containerPresentation")
|
appendTailText(" in $containerPresentation")
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-25
@@ -96,32 +96,29 @@ class CompletionBindingContextProvider(project: Project) {
|
|||||||
val psiElementsBeforeAndAfter = modificationScope?.let { collectPsiElementsBeforeAndAfter(modificationScope, inStatement) }
|
val psiElementsBeforeAndAfter = modificationScope?.let { collectPsiElementsBeforeAndAfter(modificationScope, inStatement) }
|
||||||
|
|
||||||
val prevCompletionData = prevCompletionDataCache.value.data
|
val prevCompletionData = prevCompletionDataCache.value.data
|
||||||
if (prevCompletionData == null) {
|
when {
|
||||||
log("No up-to-date data from previous completion\n")
|
prevCompletionData == null ->
|
||||||
}
|
log("No up-to-date data from previous completion\n")
|
||||||
else if (block != prevCompletionData.block) {
|
block != prevCompletionData.block ->
|
||||||
log("Not in the same block\n")
|
log("Not in the same block\n")
|
||||||
}
|
prevStatement != prevCompletionData.prevStatement ->
|
||||||
else if (prevStatement != prevCompletionData.prevStatement) {
|
log("Previous statement is not the same\n")
|
||||||
log("Previous statement is not the same\n")
|
psiElementsBeforeAndAfter != prevCompletionData.psiElementsBeforeAndAfter ->
|
||||||
}
|
log("PSI-tree has changed inside current scope\n")
|
||||||
else if (psiElementsBeforeAndAfter != prevCompletionData.psiElementsBeforeAndAfter) {
|
inStatement.isTooComplex() ->
|
||||||
log("PSI-tree has changed inside current scope\n")
|
log("Current statement is too complex to use optimization\n")
|
||||||
}
|
else -> {
|
||||||
else if (inStatement.isTooComplex()) {
|
log("Statement position is the same - analyzing only one statement:\n${inStatement.text.prependIndent(" ")}\n")
|
||||||
log("Current statement is too complex to use optimization\n")
|
LOG.debug("Reusing data from completion of \"${prevCompletionData.debugText}\"")
|
||||||
}
|
|
||||||
else {
|
|
||||||
log("Statement position is the same - analyzing only one statement:\n${inStatement.text.prependIndent(" ")}\n")
|
|
||||||
LOG.debug("Reusing data from completion of \"${prevCompletionData.debugText}\"")
|
|
||||||
|
|
||||||
//TODO: expected type?
|
//TODO: expected type?
|
||||||
val statementContext = inStatement.analyzeInContext(scope = prevCompletionData.statementResolutionScope,
|
val statementContext = inStatement.analyzeInContext(scope = prevCompletionData.statementResolutionScope,
|
||||||
contextExpression = block,
|
contextExpression = block,
|
||||||
dataFlowInfo = prevCompletionData.statementDataFlowInfo,
|
dataFlowInfo = prevCompletionData.statementDataFlowInfo,
|
||||||
isStatement = true)
|
isStatement = true)
|
||||||
// we do not update prevCompletionDataCache because the same data should work
|
// we do not update prevCompletionDataCache because the same data should work
|
||||||
return CompositeBindingContext.create(listOf(statementContext, prevCompletionData.bindingContext))
|
return CompositeBindingContext.create(listOf(statementContext, prevCompletionData.bindingContext))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val bindingContext = resolutionFacade.analyze(position.parentsWithSelf.firstIsInstance<KtElement>(), BodyResolveMode.PARTIAL_FOR_COMPLETION)
|
val bindingContext = resolutionFacade.analyze(position.parentsWithSelf.firstIsInstance<KtElement>(), BodyResolveMode.PARTIAL_FOR_COMPLETION)
|
||||||
|
|||||||
+10
-13
@@ -381,20 +381,17 @@ class LookupElementFactory(
|
|||||||
return CallableWeight(bestWeight, receiverIndexToUse)
|
return CallableWeight(bestWeight, receiverIndexToUse)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CallableDescriptor.callableWeightForReceiverType(receiverType: KotlinType, receiverParameterType: KotlinType): CallableWeightEnum? {
|
private fun CallableDescriptor.callableWeightForReceiverType(
|
||||||
if (TypeUtils.equalTypes(receiverType, receiverParameterType)) {
|
receiverType: KotlinType,
|
||||||
return when {
|
receiverParameterType: KotlinType
|
||||||
isExtensionForTypeParameter() -> CallableWeightEnum.typeParameterExtension
|
): CallableWeightEnum? = when {
|
||||||
isExtension -> CallableWeightEnum.thisTypeExtension
|
TypeUtils.equalTypes(receiverType, receiverParameterType) -> when {
|
||||||
else -> CallableWeightEnum.thisClassMember
|
isExtensionForTypeParameter() -> CallableWeightEnum.typeParameterExtension
|
||||||
}
|
isExtension -> CallableWeightEnum.thisTypeExtension
|
||||||
}
|
else -> CallableWeightEnum.thisClassMember
|
||||||
else if (receiverType.isSubtypeOf(receiverParameterType)) {
|
|
||||||
return if (isExtension) CallableWeightEnum.baseTypeExtension else CallableWeightEnum.baseClassMember
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
receiverType.isSubtypeOf(receiverParameterType) -> if (isExtension) CallableWeightEnum.baseTypeExtension else CallableWeightEnum.baseClassMember
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CallableDescriptor.isExtensionForTypeParameter(): Boolean {
|
private fun CallableDescriptor.isExtensionForTypeParameter(): Boolean {
|
||||||
|
|||||||
@@ -343,12 +343,11 @@ class ExpectedInfos(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val tail = if (argumentName == null) {
|
val tail = if (argumentName == null) {
|
||||||
if (parameter == parameters.last())
|
when {
|
||||||
rparenthTail
|
parameter == parameters.last() -> rparenthTail
|
||||||
else if (parameters.dropWhile { it != parameter }.drop(1).any(::needCommaForParameter))
|
parameters.dropWhile { it != parameter }.drop(1).any(::needCommaForParameter) -> Tail.COMMA
|
||||||
Tail.COMMA
|
else -> null
|
||||||
else
|
}
|
||||||
null
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
namedArgumentTail(argumentToParameter, argumentName, descriptor)
|
namedArgumentTail(argumentToParameter, argumentName, descriptor)
|
||||||
@@ -404,12 +403,11 @@ class ExpectedInfos(
|
|||||||
private fun namedArgumentTail(argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>, argumentName: Name, descriptor: FunctionDescriptor): Tail? {
|
private fun namedArgumentTail(argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>, argumentName: Name, descriptor: FunctionDescriptor): Tail? {
|
||||||
val usedParameterNames = (argumentToParameter.values.map { it.name } + listOf(argumentName)).toSet()
|
val usedParameterNames = (argumentToParameter.values.map { it.name } + listOf(argumentName)).toSet()
|
||||||
val notUsedParameters = descriptor.valueParameters.filter { it.name !in usedParameterNames }
|
val notUsedParameters = descriptor.valueParameters.filter { it.name !in usedParameterNames }
|
||||||
return if (notUsedParameters.isEmpty())
|
return when {
|
||||||
Tail.RPARENTH // named arguments no supported for []
|
notUsedParameters.isEmpty() -> Tail.RPARENTH // named arguments no supported for []
|
||||||
else if (notUsedParameters.all { it.hasDefaultValue() })
|
notUsedParameters.all { it.hasDefaultValue() } -> null
|
||||||
null
|
else -> Tail.COMMA
|
||||||
else
|
}
|
||||||
Tail.COMMA
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateForEqAndAssignment(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
private fun calculateForEqAndAssignment(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||||
|
|||||||
@@ -35,15 +35,14 @@ class ImportableFqNameClassifier(private val file: KtFile) {
|
|||||||
for (import in file.importDirectives) {
|
for (import in file.importDirectives) {
|
||||||
val importPath = import.importPath ?: continue
|
val importPath = import.importPath ?: continue
|
||||||
val fqName = importPath.fqName
|
val fqName = importPath.fqName
|
||||||
if (importPath.isAllUnder) {
|
when {
|
||||||
allUnderImports.add(fqName)
|
importPath.isAllUnder -> allUnderImports.add(fqName)
|
||||||
}
|
!importPath.hasAlias() -> {
|
||||||
else if (!importPath.hasAlias()) {
|
preciseImports.add(fqName)
|
||||||
preciseImports.add(fqName)
|
preciseImportPackages.add(fqName.parent())
|
||||||
preciseImportPackages.add(fqName.parent())
|
}
|
||||||
} else {
|
else -> excludedImports.add(fqName)
|
||||||
excludedImports.add(fqName)
|
// TODO: support aliased imports in completion
|
||||||
// TODO: support aliased imports in completion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,79 +174,45 @@ object KotlinNameSuggester {
|
|||||||
val typeChecker = KotlinTypeChecker.DEFAULT
|
val typeChecker = KotlinTypeChecker.DEFAULT
|
||||||
if (ErrorUtils.containsErrorType(type)) return
|
if (ErrorUtils.containsErrorType(type)) return
|
||||||
|
|
||||||
if (typeChecker.equalTypes(builtIns.booleanType, type)) {
|
when {
|
||||||
addName("b", validator)
|
typeChecker.equalTypes(builtIns.booleanType, type) -> addName("b", validator)
|
||||||
}
|
typeChecker.equalTypes(builtIns.intType, type) -> addName("i", validator)
|
||||||
else if (typeChecker.equalTypes(builtIns.intType, type)) {
|
typeChecker.equalTypes(builtIns.byteType, type) -> addName("byte", validator)
|
||||||
addName("i", validator)
|
typeChecker.equalTypes(builtIns.longType, type) -> addName("l", validator)
|
||||||
}
|
typeChecker.equalTypes(builtIns.floatType, type) -> addName("fl", validator)
|
||||||
else if (typeChecker.equalTypes(builtIns.byteType, type)) {
|
typeChecker.equalTypes(builtIns.doubleType, type) -> addName("d", validator)
|
||||||
addName("byte", validator)
|
typeChecker.equalTypes(builtIns.shortType, type) -> addName("sh", validator)
|
||||||
}
|
typeChecker.equalTypes(builtIns.charType, type) -> addName("c", validator)
|
||||||
else if (typeChecker.equalTypes(builtIns.longType, type)) {
|
typeChecker.equalTypes(builtIns.stringType, type) -> addName("s", validator)
|
||||||
addName("l", validator)
|
KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type) -> {
|
||||||
}
|
val elementType = builtIns.getArrayElementType(type)
|
||||||
else if (typeChecker.equalTypes(builtIns.floatType, type)) {
|
when {
|
||||||
addName("fl", validator)
|
typeChecker.equalTypes(builtIns.booleanType, elementType) -> addName("booleans", validator)
|
||||||
}
|
typeChecker.equalTypes(builtIns.intType, elementType) -> addName("ints", validator)
|
||||||
else if (typeChecker.equalTypes(builtIns.doubleType, type)) {
|
typeChecker.equalTypes(builtIns.byteType, elementType) -> addName("bytes", validator)
|
||||||
addName("d", validator)
|
typeChecker.equalTypes(builtIns.longType, elementType) -> addName("longs", validator)
|
||||||
}
|
typeChecker.equalTypes(builtIns.floatType, elementType) -> addName("floats", validator)
|
||||||
else if (typeChecker.equalTypes(builtIns.shortType, type)) {
|
typeChecker.equalTypes(builtIns.doubleType, elementType) -> addName("doubles", validator)
|
||||||
addName("sh", validator)
|
typeChecker.equalTypes(builtIns.shortType, elementType) -> addName("shorts", validator)
|
||||||
}
|
typeChecker.equalTypes(builtIns.charType, elementType) -> addName("chars", validator)
|
||||||
else if (typeChecker.equalTypes(builtIns.charType, type)) {
|
typeChecker.equalTypes(builtIns.stringType, elementType) -> addName("strings", validator)
|
||||||
addName("c", validator)
|
else -> {
|
||||||
}
|
val classDescriptor = TypeUtils.getClassDescriptor(elementType)
|
||||||
else if (typeChecker.equalTypes(builtIns.stringType, type)) {
|
if (classDescriptor != null) {
|
||||||
addName("s", validator)
|
val className = classDescriptor.name
|
||||||
}
|
addName("arrayOf" + StringUtil.capitalize(className.asString()) + "s", validator)
|
||||||
else if (KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type)) {
|
}
|
||||||
val elementType = builtIns.getArrayElementType(type)
|
}
|
||||||
if (typeChecker.equalTypes(builtIns.booleanType, elementType)) {
|
|
||||||
addName("booleans", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.intType, elementType)) {
|
|
||||||
addName("ints", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.byteType, elementType)) {
|
|
||||||
addName("bytes", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.longType, elementType)) {
|
|
||||||
addName("longs", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.floatType, elementType)) {
|
|
||||||
addName("floats", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.doubleType, elementType)) {
|
|
||||||
addName("doubles", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.shortType, elementType)) {
|
|
||||||
addName("shorts", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.charType, elementType)) {
|
|
||||||
addName("chars", validator)
|
|
||||||
}
|
|
||||||
else if (typeChecker.equalTypes(builtIns.stringType, elementType)) {
|
|
||||||
addName("strings", validator)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val classDescriptor = TypeUtils.getClassDescriptor(elementType)
|
|
||||||
if (classDescriptor != null) {
|
|
||||||
val className = classDescriptor.name
|
|
||||||
addName("arrayOf" + StringUtil.capitalize(className.asString()) + "s", validator)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
type.isFunctionType -> addName("function", validator)
|
||||||
else if (type.isFunctionType) {
|
else -> {
|
||||||
addName("function", validator)
|
val descriptor = type.constructor.declarationDescriptor
|
||||||
}
|
if (descriptor != null) {
|
||||||
else {
|
val className = descriptor.name
|
||||||
val descriptor = type.constructor.declarationDescriptor
|
if (!className.isSpecial) {
|
||||||
if (descriptor != null) {
|
addCamelNames(className.asString(), validator)
|
||||||
val className = descriptor.name
|
}
|
||||||
if (!className.isSpecial) {
|
|
||||||
addCamelNames(className.asString(), validator)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,25 +204,24 @@ fun KtModifierListOwner.setVisibility(visibilityModifier: KtModifierKeywordToken
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun KtDeclaration.implicitVisibility(): KtModifierKeywordToken? =
|
fun KtDeclaration.implicitVisibility(): KtModifierKeywordToken? =
|
||||||
if (this is KtConstructor<*>) {
|
when {
|
||||||
val klass = getContainingClassOrObject()
|
this is KtConstructor<*> -> {
|
||||||
if (klass is KtClass && (klass.isEnum() || klass.isSealed())) KtTokens.PRIVATE_KEYWORD
|
val klass = getContainingClassOrObject()
|
||||||
else KtTokens.DEFAULT_VISIBILITY_KEYWORD
|
if (klass is KtClass && (klass.isEnum() || klass.isSealed())) KtTokens.PRIVATE_KEYWORD
|
||||||
}
|
else KtTokens.DEFAULT_VISIBILITY_KEYWORD
|
||||||
else if (hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
|
}
|
||||||
(resolveToDescriptor(BodyResolveMode.PARTIAL) as? CallableMemberDescriptor)
|
hasModifier(KtTokens.OVERRIDE_KEYWORD) -> {
|
||||||
?.overriddenDescriptors
|
(resolveToDescriptor(BodyResolveMode.PARTIAL) as? CallableMemberDescriptor)
|
||||||
?.let { OverridingUtil.findMaxVisibility(it) }
|
?.overriddenDescriptors
|
||||||
?.toKeywordToken()
|
?.let { OverridingUtil.findMaxVisibility(it) }
|
||||||
}
|
?.toKeywordToken()
|
||||||
else {
|
}
|
||||||
KtTokens.DEFAULT_VISIBILITY_KEYWORD
|
else -> {
|
||||||
|
KtTokens.DEFAULT_VISIBILITY_KEYWORD
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtModifierListOwner.canBePrivate(): Boolean {
|
fun KtModifierListOwner.canBePrivate() = modifierList?.hasModifier(KtTokens.ABSTRACT_KEYWORD) != true
|
||||||
if (modifierList?.hasModifier(KtTokens.ABSTRACT_KEYWORD) ?: false) return false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun KtModifierListOwner.canBeProtected(): Boolean {
|
fun KtModifierListOwner.canBeProtected(): Boolean {
|
||||||
val parent = this.parent
|
val parent = this.parent
|
||||||
|
|||||||
+6
-6
@@ -75,12 +75,12 @@ class MavenPluginSourcesMoveToExecutionIntention : PsiElementBaseIntentionAction
|
|||||||
val domElement = DomManager.getDomManager(project).getDomElement(tag) as? GenericDomValue<*> ?: return
|
val domElement = DomManager.getDomManager(project).getDomElement(tag) as? GenericDomValue<*> ?: return
|
||||||
val dir = domElement.rawText ?: return
|
val dir = domElement.rawText ?: return
|
||||||
|
|
||||||
val relevantExecutions = if (domElement.getParentOfType(MavenDomBuild::class.java, false)?.sourceDirectory === domElement) {
|
val relevantExecutions = when {
|
||||||
pomFile.findKotlinExecutions(PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.Js)
|
domElement.getParentOfType(MavenDomBuild::class.java, false)?.sourceDirectory === domElement ->
|
||||||
} else if (domElement.getParentOfType(MavenDomBuild::class.java, false)?.testSourceDirectory === domElement) {
|
pomFile.findKotlinExecutions(PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.Js)
|
||||||
pomFile.findKotlinExecutions(PomFile.KotlinGoals.TestCompile, PomFile.KotlinGoals.TestJs)
|
domElement.getParentOfType(MavenDomBuild::class.java, false)?.testSourceDirectory === domElement ->
|
||||||
} else {
|
pomFile.findKotlinExecutions(PomFile.KotlinGoals.TestCompile, PomFile.KotlinGoals.TestJs)
|
||||||
emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relevantExecutions.isNotEmpty()) {
|
if (relevantExecutions.isNotEmpty()) {
|
||||||
|
|||||||
@@ -263,19 +263,11 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj
|
|||||||
targetFile: File,
|
targetFile: File,
|
||||||
jarType: OrderRootType,
|
jarType: OrderRootType,
|
||||||
useBundled: Boolean
|
useBundled: Boolean
|
||||||
): FileState {
|
): FileState = when {
|
||||||
if (targetFile.exists()) {
|
targetFile.exists() -> FileState.EXISTS
|
||||||
return FileState.EXISTS
|
getPathFromLibrary(project, jarType) != null -> FileState.COPY
|
||||||
}
|
useBundled -> FileState.DO_NOT_COPY
|
||||||
else if (getPathFromLibrary(project, jarType) != null) {
|
else -> FileState.COPY
|
||||||
return FileState.COPY
|
|
||||||
}
|
|
||||||
else if (useBundled) {
|
|
||||||
return FileState.DO_NOT_COPY
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return FileState.COPY
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPathToCopyFileTo(
|
private fun getPathToCopyFileTo(
|
||||||
|
|||||||
@@ -120,26 +120,27 @@ class DebuggerClassNameProvider(
|
|||||||
}
|
}
|
||||||
is KtClassOrObject -> {
|
is KtClassOrObject -> {
|
||||||
val enclosingElementForLocal = runReadAction { KtPsiUtil.getEnclosingElementForLocalDeclaration(element) }
|
val enclosingElementForLocal = runReadAction { KtPsiUtil.getEnclosingElementForLocalDeclaration(element) }
|
||||||
if (enclosingElementForLocal != null) { // A local class
|
when {
|
||||||
getOuterClassNamesForElement(enclosingElementForLocal)
|
enclosingElementForLocal != null ->
|
||||||
}
|
// A local class
|
||||||
else if (runReadAction { element.isObjectLiteral() }) {
|
getOuterClassNamesForElement(enclosingElementForLocal)
|
||||||
getOuterClassNamesForElement(element.relevantParentInReadAction)
|
runReadAction { element.isObjectLiteral() } ->
|
||||||
}
|
getOuterClassNamesForElement(element.relevantParentInReadAction)
|
||||||
else { // Guaranteed to be non-local class or object
|
else ->
|
||||||
element.readAction {
|
// Guaranteed to be non-local class or object
|
||||||
if (it is KtClass && runReadAction { it.isInterface() }) {
|
element.readAction {
|
||||||
val name = getNameForNonLocalClass(it)
|
if (it is KtClass && runReadAction { it.isInterface() }) {
|
||||||
|
val name = getNameForNonLocalClass(it)
|
||||||
|
|
||||||
if (name != null)
|
if (name != null)
|
||||||
Cached(listOf(name, name + JvmAbi.DEFAULT_IMPLS_SUFFIX))
|
Cached(listOf(name, name + JvmAbi.DEFAULT_IMPLS_SUFFIX))
|
||||||
else
|
else
|
||||||
ComputedClassNames.EMPTY
|
ComputedClassNames.EMPTY
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getNameForNonLocalClass(it)?.let { ComputedClassNames.Cached(it) } ?: ComputedClassNames.EMPTY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
getNameForNonLocalClass(it)?.let { ComputedClassNames.Cached(it) } ?: ComputedClassNames.EMPTY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is KtProperty -> {
|
is KtProperty -> {
|
||||||
|
|||||||
@@ -300,14 +300,13 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
|
|||||||
val jdiValue = when (this) {
|
val jdiValue = when (this) {
|
||||||
is ValueReturned -> result
|
is ValueReturned -> result
|
||||||
is ExceptionThrown -> {
|
is ExceptionThrown -> {
|
||||||
if (this.kind == ExceptionThrown.ExceptionKind.FROM_EVALUATED_CODE) {
|
when {
|
||||||
exception(InvocationException(this.exception.value as ObjectReference))
|
this.kind == ExceptionThrown.ExceptionKind.FROM_EVALUATED_CODE ->
|
||||||
}
|
exception(InvocationException(this.exception.value as ObjectReference))
|
||||||
else if (this.kind == ExceptionThrown.ExceptionKind.BROKEN_CODE) {
|
this.kind == ExceptionThrown.ExceptionKind.BROKEN_CODE ->
|
||||||
throw exception.value as Throwable
|
throw exception.value as Throwable
|
||||||
}
|
else ->
|
||||||
else {
|
exception(exception.toString())
|
||||||
exception(exception.toString())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is AbnormalTermination -> exception(message)
|
is AbnormalTermination -> exception(message)
|
||||||
|
|||||||
@@ -187,33 +187,33 @@ private class TemplateTokenSequence(private val inputString: String) : Sequence<
|
|||||||
val wrapped = '"' + input.substring(from) + '"'
|
val wrapped = '"' + input.substring(from) + '"'
|
||||||
val lexer = KotlinLexer().apply { start(wrapped) }.apply { advance() }
|
val lexer = KotlinLexer().apply { start(wrapped) }.apply { advance() }
|
||||||
|
|
||||||
if (lexer.tokenType == KtTokens.SHORT_TEMPLATE_ENTRY_START) {
|
when (lexer.tokenType) {
|
||||||
lexer.advance()
|
KtTokens.SHORT_TEMPLATE_ENTRY_START -> {
|
||||||
return if (lexer.tokenType == KtTokens.IDENTIFIER) {
|
|
||||||
from + lexer.tokenEnd - 1
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) {
|
|
||||||
var depth = 0
|
|
||||||
while (lexer.tokenType != null) {
|
|
||||||
if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) {
|
|
||||||
depth++
|
|
||||||
}
|
|
||||||
else if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END) {
|
|
||||||
depth--
|
|
||||||
if (depth == 0) {
|
|
||||||
return from + lexer.currentPosition.offset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lexer.advance()
|
lexer.advance()
|
||||||
|
return if (lexer.tokenType == KtTokens.IDENTIFIER) {
|
||||||
|
from + lexer.tokenEnd - 1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
-1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return -1
|
KtTokens.LONG_TEMPLATE_ENTRY_START -> {
|
||||||
}
|
var depth = 0
|
||||||
else {
|
while (lexer.tokenType != null) {
|
||||||
return -1
|
if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) {
|
||||||
|
depth++
|
||||||
|
}
|
||||||
|
else if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END) {
|
||||||
|
depth--
|
||||||
|
if (depth == 0) {
|
||||||
|
return from + lexer.currentPosition.offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lexer.advance()
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
else -> return -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,32 +40,34 @@ class KotlinRainbowVisitor : RainbowVisitor() {
|
|||||||
override fun clone() = KotlinRainbowVisitor()
|
override fun clone() = KotlinRainbowVisitor()
|
||||||
|
|
||||||
override fun visit(element: PsiElement) {
|
override fun visit(element: PsiElement) {
|
||||||
if (element.isRainbowDeclaration()) {
|
when {
|
||||||
val rainbowElement = (element as KtNamedDeclaration).nameIdentifier ?: return
|
element.isRainbowDeclaration() -> {
|
||||||
addRainbowHighlight(element, rainbowElement)
|
val rainbowElement = (element as KtNamedDeclaration).nameIdentifier ?: return
|
||||||
}
|
addRainbowHighlight(element, rainbowElement)
|
||||||
else if (element is KtSimpleNameExpression) {
|
}
|
||||||
val qualifiedExpression = PsiTreeUtil.getParentOfType(element, KtQualifiedExpression::class.java, true,
|
element is KtSimpleNameExpression -> {
|
||||||
KtLambdaExpression::class.java, KtValueArgumentList::class.java)
|
val qualifiedExpression = PsiTreeUtil.getParentOfType(element, KtQualifiedExpression::class.java, true,
|
||||||
if (qualifiedExpression?.selectorExpression?.isAncestor(element) == true) return
|
KtLambdaExpression::class.java, KtValueArgumentList::class.java)
|
||||||
|
if (qualifiedExpression?.selectorExpression?.isAncestor(element) == true) return
|
||||||
|
|
||||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
|
val bindingContext = element.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
|
||||||
val targets = element.getReferenceTargets(bindingContext)
|
val targets = element.getReferenceTargets(bindingContext)
|
||||||
val targetVariable = targets.firstIsInstanceOrNull<VariableDescriptor>()
|
val targetVariable = targets.firstIsInstanceOrNull<VariableDescriptor>()
|
||||||
if (targetVariable != null) {
|
if (targetVariable != null) {
|
||||||
val targetElement = DescriptorToSourceUtils.getSourceFromDescriptor(targetVariable)
|
val targetElement = DescriptorToSourceUtils.getSourceFromDescriptor(targetVariable)
|
||||||
if (targetElement.isRainbowDeclaration()) {
|
if (targetElement.isRainbowDeclaration()) {
|
||||||
addRainbowHighlight(targetElement!!, element)
|
addRainbowHighlight(targetElement!!, element)
|
||||||
}
|
}
|
||||||
else if (targetElement == null && element.getReferencedName() == "it") {
|
else if (targetElement == null && element.getReferencedName() == "it") {
|
||||||
addRainbowHighlight(element, element)
|
addRainbowHighlight(element, element)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
element is KDocName -> {
|
||||||
else if (element is KDocName) {
|
val target = element.reference?.resolve() ?: return
|
||||||
val target = element.reference?.resolve() ?: return
|
if (target.isRainbowDeclaration()) {
|
||||||
if (target.isRainbowDeclaration()) {
|
addRainbowHighlight(target, element, KDOC_LINK)
|
||||||
addRainbowHighlight(target, element, KDOC_LINK)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,14 +95,10 @@ class KotlinUnusedImportInspection : AbstractKotlinInspection() {
|
|||||||
val importPath = directive.importPath ?: continue
|
val importPath = directive.importPath ?: continue
|
||||||
if (importPath.alias != null) continue // highlighting of unused alias imports not supported yet
|
if (importPath.alias != null) continue // highlighting of unused alias imports not supported yet
|
||||||
|
|
||||||
val isUsed = if (!importPaths.add(importPath)) {
|
val isUsed = when {
|
||||||
false
|
!importPaths.add(importPath) -> false
|
||||||
}
|
importPath.isAllUnder -> importPath.fqName in parentFqNames
|
||||||
else if (importPath.isAllUnder) {
|
else -> importPath.fqName in fqNames
|
||||||
importPath.fqName in parentFqNames
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
importPath.fqName in fqNames
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isUsed) {
|
if (!isUsed) {
|
||||||
|
|||||||
@@ -72,7 +72,11 @@ class NullableBooleanElvisInspection : AbstractKotlinInspection(), CleanupLocalI
|
|||||||
val constPart = element.right as? KtConstantExpression ?: return
|
val constPart = element.right as? KtConstantExpression ?: return
|
||||||
val exprPart = element.left ?: return
|
val exprPart = element.left ?: return
|
||||||
|
|
||||||
val constValue = if (KtPsiUtil.isTrueConstant(constPart)) true else if (KtPsiUtil.isFalseConstant(constPart)) false else return
|
val constValue = when {
|
||||||
|
KtPsiUtil.isTrueConstant(constPart) -> true
|
||||||
|
KtPsiUtil.isFalseConstant(constPart) -> false
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
val equalityCheckExpression = element.replaced(KtPsiFactory(constPart).buildExpression {
|
val equalityCheckExpression = element.replaced(KtPsiFactory(constPart).buildExpression {
|
||||||
appendExpression(exprPart)
|
appendExpression(exprPart)
|
||||||
appendFixedText(if (constValue) " != false" else " == true")
|
appendFixedText(if (constValue) " != false" else " == true")
|
||||||
|
|||||||
+5
-1
@@ -47,7 +47,11 @@ class NullableBooleanEqualityCheckToElvisIntention : SelfTargetingIntention<KtBi
|
|||||||
val constPart = element.left as? KtConstantExpression ?:
|
val constPart = element.left as? KtConstantExpression ?:
|
||||||
element.right as? KtConstantExpression ?: return
|
element.right as? KtConstantExpression ?: return
|
||||||
val exprPart = (if (element.right == constPart) element.left else element.right) ?: return
|
val exprPart = (if (element.right == constPart) element.left else element.right) ?: return
|
||||||
val constValue = if (KtPsiUtil.isTrueConstant(constPart)) true else if (KtPsiUtil.isFalseConstant(constPart)) false else return
|
val constValue = when {
|
||||||
|
KtPsiUtil.isTrueConstant(constPart) -> true
|
||||||
|
KtPsiUtil.isFalseConstant(constPart) -> false
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
val factory = KtPsiFactory(constPart)
|
val factory = KtPsiFactory(constPart)
|
||||||
val elvis = factory.createExpressionByPattern("$0 ?: ${!constValue}", exprPart)
|
val elvis = factory.createExpressionByPattern("$0 ?: ${!constValue}", exprPart)
|
||||||
|
|||||||
+4
-7
@@ -168,14 +168,11 @@ data class IfThenToSelectData(
|
|||||||
if (condition is KtIsExpression) newReceiver!! else baseClause
|
if (condition is KtIsExpression) newReceiver!! else baseClause
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (condition is KtIsExpression) {
|
when {
|
||||||
(baseClause as KtDotQualifiedExpression).replaceFirstReceiver(
|
condition is KtIsExpression -> (baseClause as KtDotQualifiedExpression).replaceFirstReceiver(
|
||||||
factory, newReceiver!!, safeAccess = true)
|
factory, newReceiver!!, safeAccess = true)
|
||||||
}
|
hasImplicitReceiver() -> factory.createExpressionByPattern("this?.$0", baseClause).insertSafeCalls(factory)
|
||||||
else if (hasImplicitReceiver()) {
|
else -> baseClause.insertSafeCalls(factory)
|
||||||
factory.createExpressionByPattern("this?.$0", baseClause).insertSafeCalls(factory)
|
|
||||||
} else {
|
|
||||||
baseClause.insertSafeCalls(factory)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-24
@@ -116,14 +116,10 @@ class MaxOrMinTransformation(
|
|||||||
val functionName = if (isMax) "max" else "min"
|
val functionName = if (isMax) "max" else "min"
|
||||||
val arguments = assignment.right.extractStaticFunctionCallArguments("java.lang.Math." + functionName) ?: return null
|
val arguments = assignment.right.extractStaticFunctionCallArguments("java.lang.Math." + functionName) ?: return null
|
||||||
if (arguments.size != 2) return null
|
if (arguments.size != 2) return null
|
||||||
val value = if (arguments[0].isVariableReference(variableInitialization.variable)) {
|
val value = when {
|
||||||
arguments[1] ?: return null
|
arguments[0].isVariableReference(variableInitialization.variable) -> arguments[1] ?: return null
|
||||||
}
|
arguments[1].isVariableReference(variableInitialization.variable) -> arguments[0] ?: return null
|
||||||
else if (arguments[1].isVariableReference(variableInitialization.variable)) {
|
else -> return null
|
||||||
arguments[0] ?: return null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val mapTransformation = if (value.isVariableReference(state.inputVariable))
|
val mapTransformation = if (value.isVariableReference(state.inputVariable))
|
||||||
@@ -148,14 +144,10 @@ class MaxOrMinTransformation(
|
|||||||
if (comparison !in setOf(KtTokens.GT, KtTokens.LT, KtTokens.GTEQ, KtTokens.LTEQ)) return null
|
if (comparison !in setOf(KtTokens.GT, KtTokens.LT, KtTokens.GTEQ, KtTokens.LTEQ)) return null
|
||||||
val left = condition.left as? KtNameReferenceExpression ?: return null
|
val left = condition.left as? KtNameReferenceExpression ?: return null
|
||||||
val right = condition.right as? KtNameReferenceExpression ?: return null
|
val right = condition.right as? KtNameReferenceExpression ?: return null
|
||||||
val otherHand = if (left.isVariableReference(inputVariable)) {
|
val otherHand = when {
|
||||||
right
|
left.isVariableReference(inputVariable) -> right
|
||||||
}
|
right.isVariableReference(inputVariable) -> left
|
||||||
else if (right.isVariableReference(inputVariable)) {
|
else -> return null
|
||||||
left
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val variableInitialization = otherHand.findVariableInitializationBeforeLoop(loop, checkNoOtherUsagesInLoop = false)
|
val variableInitialization = otherHand.findVariableInitializationBeforeLoop(loop, checkNoOtherUsagesInLoop = false)
|
||||||
@@ -163,14 +155,10 @@ class MaxOrMinTransformation(
|
|||||||
|
|
||||||
if (!assignmentTarget.isVariableReference(variableInitialization.variable)) return null
|
if (!assignmentTarget.isVariableReference(variableInitialization.variable)) return null
|
||||||
|
|
||||||
val valueToBeVariable = if (valueAssignedIfTrue.isVariableReference(inputVariable)) {
|
val valueToBeVariable = when {
|
||||||
valueAssignedIfFalse
|
valueAssignedIfTrue.isVariableReference(inputVariable) -> valueAssignedIfFalse
|
||||||
}
|
valueAssignedIfFalse.isVariableReference(inputVariable) -> valueAssignedIfTrue
|
||||||
else if (valueAssignedIfFalse.isVariableReference(inputVariable)) {
|
else -> return null
|
||||||
valueAssignedIfTrue
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
if (valueToBeVariable != null && !valueToBeVariable.isVariableReference(variableInitialization.variable)) return null
|
if (valueToBeVariable != null && !valueToBeVariable.isVariableReference(variableInitialization.variable)) return null
|
||||||
|
|
||||||
|
|||||||
@@ -54,14 +54,10 @@ open class KotlinDefaultNamedDeclarationPresentation(private val declaration: Kt
|
|||||||
qualifiedContainer
|
qualifiedContainer
|
||||||
}
|
}
|
||||||
val receiverTypeRef = (declaration as? KtCallableDeclaration)?.receiverTypeReference
|
val receiverTypeRef = (declaration as? KtCallableDeclaration)?.receiverTypeReference
|
||||||
if (receiverTypeRef != null) {
|
return when {
|
||||||
return "(for " + receiverTypeRef.text + " in " + containerText + ")"
|
receiverTypeRef != null -> "(for " + receiverTypeRef.text + " in " + containerText + ")"
|
||||||
}
|
parent is KtFile -> "($containerText)"
|
||||||
else if (parent is KtFile) {
|
else -> "(in $containerText)"
|
||||||
return "(" + containerText + ")"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return "(in " + containerText + ")"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,15 +63,13 @@ abstract class ChangeFunctionSignatureFix(
|
|||||||
val argumentName = argument.getArgumentName()
|
val argumentName = argument.getArgumentName()
|
||||||
val expression = argument.getArgumentExpression()
|
val expression = argument.getArgumentExpression()
|
||||||
|
|
||||||
return if (argumentName != null) {
|
return when {
|
||||||
KotlinNameSuggester.suggestNameByName(argumentName.asName.asString(), validator)
|
argumentName != null -> KotlinNameSuggester.suggestNameByName(argumentName.asName.asString(), validator)
|
||||||
}
|
expression != null -> {
|
||||||
else if (expression != null) {
|
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
KotlinNameSuggester.suggestNamesByExpressionAndType(expression, null, bindingContext, validator, "param").first()
|
||||||
KotlinNameSuggester.suggestNamesByExpressionAndType(expression, null, bindingContext, validator, "param").first()
|
}
|
||||||
}
|
else -> KotlinNameSuggester.suggestNameByName("param", validator)
|
||||||
else {
|
|
||||||
KotlinNameSuggester.suggestNameByName("param", validator)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,16 +100,20 @@ class ReplaceInfixOrOperatorCallFix(
|
|||||||
val parent = expression.parent
|
val parent = expression.parent
|
||||||
return when (parent) {
|
return when (parent) {
|
||||||
is KtBinaryExpression -> {
|
is KtBinaryExpression -> {
|
||||||
if (parent.left == null || parent.right == null) null
|
when {
|
||||||
else if (parent.operationToken == KtTokens.EQ) null
|
parent.left == null || parent.right == null -> null
|
||||||
else if (parent.operationToken in OperatorConventions.COMPARISON_OPERATIONS) null
|
parent.operationToken == KtTokens.EQ -> null
|
||||||
else ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType())
|
parent.operationToken in OperatorConventions.COMPARISON_OPERATIONS -> null
|
||||||
|
else -> ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is KtCallExpression -> {
|
is KtCallExpression -> {
|
||||||
if (parent.calleeExpression == null) null
|
when {
|
||||||
else if (parent.parent is KtQualifiedExpression) null
|
parent.calleeExpression == null -> null
|
||||||
else if (parent.getResolvedCall(parent.analyze())?.getImplicitReceiverValue() != null) null
|
parent.parent is KtQualifiedExpression -> null
|
||||||
else ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType())
|
parent.getResolvedCall(parent.analyze())?.getImplicitReceiverValue() != null -> null
|
||||||
|
else -> ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,14 +41,10 @@ class SpecifyTypeExplicitlyFix : PsiElementBaseIntentionAction() {
|
|||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean {
|
override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean {
|
||||||
val declaration = declarationByElement(element)
|
val declaration = declarationByElement(element)
|
||||||
if (declaration is KtProperty) {
|
text = when (declaration) {
|
||||||
text = "Specify type explicitly"
|
is KtProperty -> "Specify type explicitly"
|
||||||
}
|
is KtNamedFunction -> "Specify return type explicitly"
|
||||||
else if (declaration is KtNamedFunction) {
|
else -> return false
|
||||||
text = "Specify return type explicitly"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !SpecifyTypeExplicitlyIntention.getTypeForDeclaration(declaration).isError
|
return !SpecifyTypeExplicitlyIntention.getTypeForDeclaration(declaration).isError
|
||||||
|
|||||||
+43
-34
@@ -96,19 +96,23 @@ class MigrateExternalExtensionFix(declaration: KtNamedDeclaration)
|
|||||||
val nativeAnnotations = ArrayList<KtAnnotationEntry>()
|
val nativeAnnotations = ArrayList<KtAnnotationEntry>()
|
||||||
|
|
||||||
declaration.modifierList?.annotationEntries?.forEach {
|
declaration.modifierList?.annotationEntries?.forEach {
|
||||||
if (it.isJsAnnotation(PredefinedAnnotation.NATIVE_GETTER)) {
|
when {
|
||||||
isGetter = true
|
it.isJsAnnotation(PredefinedAnnotation.NATIVE_GETTER) -> {
|
||||||
nativeAnnotations.add(it)
|
isGetter = true
|
||||||
} else if (it.isJsAnnotation(PredefinedAnnotation.NATIVE_SETTER)) {
|
nativeAnnotations.add(it)
|
||||||
isSetter = true
|
}
|
||||||
nativeAnnotations.add(it)
|
it.isJsAnnotation(PredefinedAnnotation.NATIVE_SETTER) -> {
|
||||||
} else if (it.isJsAnnotation(PredefinedAnnotation.NATIVE_INVOKE)) {
|
isSetter = true
|
||||||
isInvoke = true
|
nativeAnnotations.add(it)
|
||||||
nativeAnnotations.add(it)
|
}
|
||||||
} else if (it.isJsAnnotation(PredefinedAnnotation.NATIVE)) {
|
it.isJsAnnotation(PredefinedAnnotation.NATIVE_INVOKE) -> {
|
||||||
nativeAnnotations.add(it)
|
isInvoke = true
|
||||||
nativeAnnotation = it
|
nativeAnnotations.add(it)
|
||||||
|
}
|
||||||
|
it.isJsAnnotation(PredefinedAnnotation.NATIVE) -> {
|
||||||
|
nativeAnnotations.add(it)
|
||||||
|
nativeAnnotation = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return JsNativeAnnotations(nativeAnnotations, nativeAnnotation, isGetter, isSetter, isInvoke)
|
return JsNativeAnnotations(nativeAnnotations, nativeAnnotation, isGetter, isSetter, isInvoke)
|
||||||
@@ -122,30 +126,35 @@ class MigrateExternalExtensionFix(declaration: KtNamedDeclaration)
|
|||||||
val ktPsiFactory = KtPsiFactory(declaration)
|
val ktPsiFactory = KtPsiFactory(declaration)
|
||||||
val body = ktPsiFactory.buildExpression {
|
val body = ktPsiFactory.buildExpression {
|
||||||
appendName(Name.identifier("asDynamic"))
|
appendName(Name.identifier("asDynamic"))
|
||||||
if (annotations.isGetter) {
|
when {
|
||||||
appendFixedText("()")
|
annotations.isGetter -> {
|
||||||
if (declaration is KtNamedFunction) {
|
appendFixedText("()")
|
||||||
appendParameters(declaration, "[", "]")
|
if (declaration is KtNamedFunction) {
|
||||||
}
|
appendParameters(declaration, "[", "]")
|
||||||
} else if (annotations.isSetter) {
|
|
||||||
appendFixedText("()")
|
|
||||||
if (declaration is KtNamedFunction) {
|
|
||||||
appendParameters(declaration, "[", "]", skipLast = true)
|
|
||||||
declaration.valueParameters.last().nameAsName?.let {
|
|
||||||
appendFixedText(" = ")
|
|
||||||
appendName(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (annotations.isInvoke) {
|
annotations.isSetter -> {
|
||||||
appendFixedText("()")
|
appendFixedText("()")
|
||||||
if (declaration is KtNamedFunction) {
|
if (declaration is KtNamedFunction) {
|
||||||
appendParameters(declaration, "(", ")")
|
appendParameters(declaration, "[", "]", skipLast = true)
|
||||||
|
declaration.valueParameters.last().nameAsName?.let {
|
||||||
|
appendFixedText(" = ")
|
||||||
|
appendName(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
annotations.isInvoke -> {
|
||||||
appendFixedText("().")
|
appendFixedText("()")
|
||||||
appendName(name)
|
if (declaration is KtNamedFunction) {
|
||||||
if (declaration is KtNamedFunction) {
|
appendParameters(declaration, "(", ")")
|
||||||
appendParameters(declaration, "(", ")")
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
appendFixedText("().")
|
||||||
|
appendName(name)
|
||||||
|
if (declaration is KtNamedFunction) {
|
||||||
|
appendParameters(declaration, "(", ")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-32
@@ -122,33 +122,19 @@ class KotlinChangeSignatureData(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getParameters(): List<KotlinParameterInfo> {
|
override fun getParameters(): List<KotlinParameterInfo> = parameters
|
||||||
return parameters
|
|
||||||
|
override fun getName() = when (baseDescriptor) {
|
||||||
|
is ConstructorDescriptor -> baseDescriptor.containingDeclaration.name.asString()
|
||||||
|
is AnonymousFunctionDescriptor -> ""
|
||||||
|
else -> baseDescriptor.name.asString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getName(): String {
|
override fun getParametersCount(): Int = baseDescriptor.valueParameters.size
|
||||||
if (baseDescriptor is ConstructorDescriptor) {
|
|
||||||
return baseDescriptor.containingDeclaration.name.asString()
|
|
||||||
}
|
|
||||||
else if (baseDescriptor is AnonymousFunctionDescriptor) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return baseDescriptor.name.asString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getParametersCount(): Int {
|
override fun getVisibility(): Visibility = baseDescriptor.visibility
|
||||||
return baseDescriptor.valueParameters.size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getVisibility(): Visibility {
|
override fun getMethod(): PsiElement = baseDeclaration
|
||||||
return baseDescriptor.visibility
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getMethod(): PsiElement {
|
|
||||||
return baseDeclaration
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canChangeVisibility(): Boolean {
|
override fun canChangeVisibility(): Boolean {
|
||||||
if (DescriptorUtils.isLocal(baseDescriptor)) return false
|
if (DescriptorUtils.isLocal(baseDescriptor)) return false
|
||||||
@@ -156,15 +142,10 @@ class KotlinChangeSignatureData(
|
|||||||
return !(baseDescriptor is AnonymousFunctionDescriptor || parent is ClassDescriptor && parent.kind == ClassKind.INTERFACE)
|
return !(baseDescriptor is AnonymousFunctionDescriptor || parent is ClassDescriptor && parent.kind == ClassKind.INTERFACE)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canChangeParameters(): Boolean {
|
override fun canChangeParameters() = true
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canChangeName(): Boolean {
|
override fun canChangeName() = !(baseDescriptor is ConstructorDescriptor || baseDescriptor is AnonymousFunctionDescriptor)
|
||||||
return !(baseDescriptor is ConstructorDescriptor || baseDescriptor is AnonymousFunctionDescriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canChangeReturnType(): MethodDescriptor.ReadWriteOption {
|
override fun canChangeReturnType(): MethodDescriptor.ReadWriteOption =
|
||||||
return if (baseDescriptor is ConstructorDescriptor) MethodDescriptor.ReadWriteOption.None else MethodDescriptor.ReadWriteOption.ReadWrite
|
if (baseDescriptor is ConstructorDescriptor) MethodDescriptor.ReadWriteOption.None else MethodDescriptor.ReadWriteOption.ReadWrite
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-13
@@ -248,16 +248,18 @@ class KotlinChangeSignatureDialog(
|
|||||||
return JBTableRow { column ->
|
return JBTableRow { column ->
|
||||||
val columnInfo = parametersTableModel.columnInfos[column]
|
val columnInfo = parametersTableModel.columnInfos[column]
|
||||||
|
|
||||||
if (KotlinPrimaryConstructorParameterTableModel.isValVarColumn(columnInfo))
|
when {
|
||||||
(components[column] as @Suppress("NO_TYPE_ARGUMENTS_ON_RHS") JComboBox).selectedItem
|
KotlinPrimaryConstructorParameterTableModel.isValVarColumn(columnInfo) ->
|
||||||
else if (KotlinCallableParameterTableModel.isTypeColumn(columnInfo))
|
(components[column] as @Suppress("NO_TYPE_ARGUMENTS_ON_RHS") JComboBox).selectedItem
|
||||||
item.typeCodeFragment
|
KotlinCallableParameterTableModel.isTypeColumn(columnInfo) ->
|
||||||
else if (KotlinCallableParameterTableModel.isNameColumn(columnInfo))
|
item.typeCodeFragment
|
||||||
(components[column] as EditorTextField).text
|
KotlinCallableParameterTableModel.isNameColumn(columnInfo) ->
|
||||||
else if (KotlinCallableParameterTableModel.isDefaultValueColumn(columnInfo))
|
(components[column] as EditorTextField).text
|
||||||
item.defaultValueCodeFragment
|
KotlinCallableParameterTableModel.isDefaultValueColumn(columnInfo) ->
|
||||||
else
|
item.defaultValueCodeFragment
|
||||||
null
|
else ->
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,9 +293,11 @@ class KotlinChangeSignatureDialog(
|
|||||||
|
|
||||||
override fun getPreferredFocusedComponent(): JComponent {
|
override fun getPreferredFocusedComponent(): JComponent {
|
||||||
val me = mouseEvent
|
val me = mouseEvent
|
||||||
val index = if (me != null)
|
val index = when {
|
||||||
getEditorIndex(me.point.getX().toInt())
|
me != null -> getEditorIndex(me.point.getX().toInt())
|
||||||
else if (myMethod.kind === Kind.PRIMARY_CONSTRUCTOR) 1 else 0
|
myMethod.kind === Kind.PRIMARY_CONSTRUCTOR -> 1
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
val component = components[index]
|
val component = components[index]
|
||||||
return if (component is EditorTextField) component.focusTarget else component
|
return if (component is EditorTextField) component.focusTarget else component
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-8
@@ -353,16 +353,12 @@ private fun makeCall(
|
|||||||
)
|
)
|
||||||
|
|
||||||
is Jump -> {
|
is Jump -> {
|
||||||
if (outputValue.elementToInsertAfterCall == null) {
|
when {
|
||||||
Collections.singletonList(psiFactory.createExpression(callText))
|
outputValue.elementToInsertAfterCall == null -> Collections.singletonList(psiFactory.createExpression(callText))
|
||||||
}
|
outputValue.conditional -> Collections.singletonList(
|
||||||
else if (outputValue.conditional) {
|
|
||||||
Collections.singletonList(
|
|
||||||
psiFactory.createExpression("if ($callText) ${outputValue.elementToInsertAfterCall.text}")
|
psiFactory.createExpression("if ($callText) ${outputValue.elementToInsertAfterCall.text}")
|
||||||
)
|
)
|
||||||
}
|
else -> listOf(
|
||||||
else {
|
|
||||||
listOf(
|
|
||||||
psiFactory.createExpression(callText),
|
psiFactory.createExpression(callText),
|
||||||
newLine,
|
newLine,
|
||||||
psiFactory.createExpression(outputValue.elementToInsertAfterCall.text!!)
|
psiFactory.createExpression(outputValue.elementToInsertAfterCall.text!!)
|
||||||
|
|||||||
+7
-8
@@ -134,14 +134,13 @@ fun IntroduceTypeAliasDescriptor.validate(): IntroduceTypeAliasDescriptorWithCon
|
|||||||
val conflicts = MultiMap<PsiElement, String>()
|
val conflicts = MultiMap<PsiElement, String>()
|
||||||
|
|
||||||
val originalType = originalData.originalTypeElement
|
val originalType = originalData.originalTypeElement
|
||||||
if (name.isEmpty()) {
|
when {
|
||||||
conflicts.putValue(originalType, "No name provided for type alias")
|
name.isEmpty() ->
|
||||||
}
|
conflicts.putValue(originalType, "No name provided for type alias")
|
||||||
else if (!KotlinNameSuggester.isIdentifier(name)) {
|
!KotlinNameSuggester.isIdentifier(name) ->
|
||||||
conflicts.putValue(originalType, "Type alias name must be a valid identifier: $name")
|
conflicts.putValue(originalType, "Type alias name must be a valid identifier: $name")
|
||||||
}
|
originalData.getTargetScope().findClassifier(Name.identifier(name), NoLookupLocation.FROM_IDE) != null ->
|
||||||
else if (originalData.getTargetScope().findClassifier(Name.identifier(name), NoLookupLocation.FROM_IDE) != null) {
|
conflicts.putValue(originalType, "Type $name already exists in the target scope")
|
||||||
conflicts.putValue(originalType, "Type $name already exists in the target scope")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeParameters.distinctBy { it.name }.size != typeParameters.size) {
|
if (typeParameters.distinctBy { it.name }.size != typeParameters.size) {
|
||||||
|
|||||||
@@ -97,12 +97,14 @@ class KotlinRunConfigurationProducer : RunConfigurationProducer<JetRunConfigurat
|
|||||||
null -> null
|
null -> null
|
||||||
is KtFile -> container.javaFileFacadeFqName.asString()
|
is KtFile -> container.javaFileFacadeFqName.asString()
|
||||||
is KtClassOrObject -> {
|
is KtClassOrObject -> {
|
||||||
if (!container.isValid)
|
if (!container.isValid) {
|
||||||
null
|
null
|
||||||
|
}
|
||||||
else if (container is KtObjectDeclaration && container.isCompanion()) {
|
else if (container is KtObjectDeclaration && container.isCompanion()) {
|
||||||
val containerClass = container.getParentOfType<KtClass>(true)
|
val containerClass = container.getParentOfType<KtClass>(true)
|
||||||
containerClass?.toLightClass()?.let { ClassUtil.getJVMClassName(it) }
|
containerClass?.toLightClass()?.let { ClassUtil.getJVMClassName(it) }
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
container.toLightClass()?.let { ClassUtil.getJVMClassName(it) }
|
container.toLightClass()?.let { ClassUtil.getJVMClassName(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,17 +115,19 @@ fun notifyOutdatedKotlinRuntime(project: Project, outdatedLibraries: Collection<
|
|||||||
Notifications.Bus.notify(Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Outdated Kotlin Runtime", message,
|
Notifications.Bus.notify(Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Outdated Kotlin Runtime", message,
|
||||||
NotificationType.WARNING, NotificationListener { notification, event ->
|
NotificationType.WARNING, NotificationListener { notification, event ->
|
||||||
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||||
if ("update" == event.description) {
|
when {
|
||||||
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library }
|
"update" == event.description -> {
|
||||||
ApplicationManager.getApplication().invokeLater {
|
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library }
|
||||||
updateLibraries(project, outdatedLibraries)
|
ApplicationManager.getApplication().invokeLater {
|
||||||
|
updateLibraries(project, outdatedLibraries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"ignore" == event.description -> {
|
||||||
|
PropertiesComponent.getInstance(project).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw AssertionError()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if ("ignore" == event.description) {
|
|
||||||
PropertiesComponent.getInstance(project).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw AssertionError()
|
|
||||||
}
|
}
|
||||||
notification.expire()
|
notification.expire()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -345,44 +345,44 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
if (target is KtLightMethod) {
|
if (target is KtLightMethod) {
|
||||||
val origin = target.kotlinOrigin
|
val origin = target.kotlinOrigin
|
||||||
val isTopLevel = origin?.getStrictParentOfType<KtClassOrObject>() == null
|
val isTopLevel = origin?.getStrictParentOfType<KtClassOrObject>() == null
|
||||||
if (origin is KtProperty || origin is KtPropertyAccessor || origin is KtParameter) {
|
when (origin) {
|
||||||
val property = if (origin is KtPropertyAccessor)
|
is KtProperty, is KtPropertyAccessor, is KtParameter -> {
|
||||||
origin.parent as KtProperty
|
val property = if (origin is KtPropertyAccessor)
|
||||||
else
|
origin.parent as KtProperty
|
||||||
origin as KtNamedDeclaration
|
else
|
||||||
val parameterCount = target.parameterList.parameters.size
|
origin as KtNamedDeclaration
|
||||||
if (parameterCount == arguments.size) {
|
val parameterCount = target.parameterList.parameters.size
|
||||||
val propertyName = Identifier.withNoPrototype(property.name!!, isNullable)
|
if (parameterCount == arguments.size) {
|
||||||
val isExtension = property.isExtensionDeclaration()
|
val propertyName = Identifier.withNoPrototype(property.name!!, isNullable)
|
||||||
val propertyAccess = if (isTopLevel) {
|
val isExtension = property.isExtensionDeclaration()
|
||||||
if (isExtension)
|
val propertyAccess = if (isTopLevel) {
|
||||||
QualifiedExpression(codeConverter.convertExpression(arguments.firstOrNull(), shouldParenthesize = true), propertyName, null).assignNoPrototype()
|
if (isExtension)
|
||||||
else
|
QualifiedExpression(codeConverter.convertExpression(arguments.firstOrNull(), shouldParenthesize = true), propertyName, null).assignNoPrototype()
|
||||||
|
else
|
||||||
|
propertyName
|
||||||
|
}
|
||||||
|
else if (qualifier != null) {
|
||||||
|
QualifiedExpression(codeConverter.convertExpression(qualifier), propertyName, dot).assignNoPrototype()
|
||||||
|
}
|
||||||
|
else {
|
||||||
propertyName
|
propertyName
|
||||||
}
|
|
||||||
else if (qualifier != null) {
|
|
||||||
QualifiedExpression(codeConverter.convertExpression(qualifier), propertyName, dot).assignNoPrototype()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
propertyName
|
|
||||||
}
|
|
||||||
|
|
||||||
when(if (isExtension) parameterCount - 1 else parameterCount) {
|
|
||||||
0 /* getter */ -> {
|
|
||||||
result = propertyAccess
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1 /* setter */ -> {
|
when(if (isExtension) parameterCount - 1 else parameterCount) {
|
||||||
val argument = codeConverter.convertExpression(arguments[if (isExtension) 1 else 0])
|
0 /* getter */ -> {
|
||||||
result = AssignmentExpression(propertyAccess, argument, Operator.EQ)
|
result = propertyAccess
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
1 /* setter */ -> {
|
||||||
|
val argument = codeConverter.convertExpression(arguments[if (isExtension) 1 else 0])
|
||||||
|
result = AssignmentExpression(propertyAccess, argument, Operator.EQ)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
is KtFunction -> if (isTopLevel) {
|
||||||
else if (origin is KtFunction) {
|
|
||||||
if (isTopLevel) {
|
|
||||||
result = if (origin.isExtensionDeclaration()) {
|
result = if (origin.isExtensionDeclaration()) {
|
||||||
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), shouldParenthesize = true)
|
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), shouldParenthesize = true)
|
||||||
MethodCallExpression.build(qualifier,
|
MethodCallExpression.build(qualifier,
|
||||||
@@ -401,27 +401,27 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
null -> {
|
||||||
else if (origin == null){
|
val resolvedQualifier = (methodExpr.qualifier as? PsiReferenceExpression)?.resolve()
|
||||||
val resolvedQualifier = (methodExpr.qualifier as? PsiReferenceExpression)?.resolve()
|
if (isFacadeClassFromLibrary(resolvedQualifier)) {
|
||||||
if (isFacadeClassFromLibrary(resolvedQualifier)) {
|
result = if (target.isKotlinExtensionFunction()) {
|
||||||
result = if (target.isKotlinExtensionFunction()) {
|
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), shouldParenthesize = true)
|
||||||
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), shouldParenthesize = true)
|
MethodCallExpression.build(qualifier,
|
||||||
MethodCallExpression.build(qualifier,
|
methodExpr.referenceName!!,
|
||||||
methodExpr.referenceName!!,
|
convertArguments(expression, isExtension = true),
|
||||||
convertArguments(expression, isExtension = true),
|
typeArguments,
|
||||||
typeArguments,
|
isNullable,
|
||||||
isNullable,
|
dot)
|
||||||
dot)
|
}
|
||||||
|
else {
|
||||||
|
MethodCallExpression.build(null,
|
||||||
|
methodExpr.referenceName!!,
|
||||||
|
convertArguments(expression),
|
||||||
|
typeArguments,
|
||||||
|
isNullable)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
MethodCallExpression.build(null,
|
|
||||||
methodExpr.referenceName!!,
|
|
||||||
convertArguments(expression),
|
|
||||||
typeArguments,
|
|
||||||
isNullable)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -826,39 +826,40 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
|
|
||||||
val specialMethod = method?.let { SpecialMethod.match(it, callParams.size, converter.services) }
|
val specialMethod = method?.let { SpecialMethod.match(it, callParams.size, converter.services) }
|
||||||
val statement: Statement
|
val statement: Statement
|
||||||
if (expression.isConstructor) {
|
when {
|
||||||
val argumentList = ArgumentList.withNoPrototype(callParams.map { it.first })
|
expression.isConstructor -> {
|
||||||
statement = MethodCallExpression.buildNonNull(null, convertMethodReferenceQualifier(qualifier), argumentList)
|
val argumentList = ArgumentList.withNoPrototype(callParams.map { it.first })
|
||||||
}
|
statement = MethodCallExpression.buildNonNull(null, convertMethodReferenceQualifier(qualifier), argumentList)
|
||||||
else if (specialMethod != null) {
|
|
||||||
val factory = PsiElementFactory.SERVICE.getInstance(converter.project)
|
|
||||||
val fakeReceiver = receiver?.let {
|
|
||||||
val psiExpression = qualifier as? PsiExpression ?: factory.createExpressionFromText("fakeReceiver", null)
|
|
||||||
psiExpression.convertedExpression = it.first
|
|
||||||
psiExpression
|
|
||||||
}
|
}
|
||||||
val fakeParams = callParams.mapIndexed {
|
specialMethod != null -> {
|
||||||
i, param ->
|
val factory = PsiElementFactory.SERVICE.getInstance(converter.project)
|
||||||
with(factory.createExpressionFromText("fake$i", null)) {
|
val fakeReceiver = receiver?.let {
|
||||||
this.convertedExpression = param.first
|
val psiExpression = qualifier as? PsiExpression ?: factory.createExpressionFromText("fakeReceiver", null)
|
||||||
this
|
psiExpression.convertedExpression = it.first
|
||||||
|
psiExpression
|
||||||
}
|
}
|
||||||
}
|
val fakeParams = callParams.mapIndexed { i, param ->
|
||||||
val patchedConverter = codeConverter.withSpecialExpressionConverter(object : SpecialExpressionConverter {
|
with(factory.createExpressionFromText("fake$i", null)) {
|
||||||
override fun convertExpression(expression: PsiExpression, codeConverter: CodeConverter): Expression? {
|
this.convertedExpression = param.first
|
||||||
val convertedExpression = expression.convertedExpression
|
this
|
||||||
expression.convertedExpression = null
|
}
|
||||||
return convertedExpression
|
|
||||||
}
|
}
|
||||||
})
|
val patchedConverter = codeConverter.withSpecialExpressionConverter(object : SpecialExpressionConverter {
|
||||||
|
override fun convertExpression(expression: PsiExpression, codeConverter: CodeConverter): Expression? {
|
||||||
|
val convertedExpression = expression.convertedExpression
|
||||||
|
expression.convertedExpression = null
|
||||||
|
return convertedExpression
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
val callData = SpecialMethod.ConvertCallData(fakeReceiver, fakeParams, emptyList(), null, null, null, patchedConverter)
|
val callData = SpecialMethod.ConvertCallData(fakeReceiver, fakeParams, emptyList(), null, null, null, patchedConverter)
|
||||||
statement = specialMethod.convertCall(callData)!!
|
statement = specialMethod.convertCall(callData)!!
|
||||||
}
|
}
|
||||||
else {
|
else -> {
|
||||||
val referenceName = expression.referenceName!!
|
val referenceName = expression.referenceName!!
|
||||||
val argumentList = ArgumentList.withNoPrototype(callParams.map { it.first })
|
val argumentList = ArgumentList.withNoPrototype(callParams.map { it.first })
|
||||||
statement = MethodCallExpression.buildNonNull(receiver?.first, referenceName, argumentList)
|
statement = MethodCallExpression.buildNonNull(receiver?.first, referenceName, argumentList)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
statement.assignNoPrototype()
|
statement.assignNoPrototype()
|
||||||
|
|||||||
@@ -104,13 +104,14 @@ class ForConverter(
|
|||||||
statement.isInSingleLine()).assignNoPrototype()
|
statement.isInSingleLine()).assignNoPrototype()
|
||||||
if (initializationConverted.isEmpty) return whileStatement
|
if (initializationConverted.isEmpty) return whileStatement
|
||||||
|
|
||||||
val kind = if (statement.parents.filter { it !is PsiLabeledStatement }.first() !is PsiCodeBlock) {
|
val kind = when {
|
||||||
WhileWithInitializationPseudoStatement.Kind.WITH_BLOCK
|
statement.parents.filter { it !is PsiLabeledStatement }.first() !is PsiCodeBlock ->
|
||||||
|
WhileWithInitializationPseudoStatement.Kind.WITH_BLOCK
|
||||||
|
hasNameConflict() ->
|
||||||
|
WhileWithInitializationPseudoStatement.Kind.WITH_RUN_BLOCK
|
||||||
|
else ->
|
||||||
|
WhileWithInitializationPseudoStatement.Kind.SIMPLE
|
||||||
}
|
}
|
||||||
else if (hasNameConflict())
|
|
||||||
WhileWithInitializationPseudoStatement.Kind.WITH_RUN_BLOCK
|
|
||||||
else
|
|
||||||
WhileWithInitializationPseudoStatement.Kind.SIMPLE
|
|
||||||
return WhileWithInitializationPseudoStatement(initializationConverted, whileStatement, kind)
|
return WhileWithInitializationPseudoStatement(initializationConverted, whileStatement, kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -266,12 +266,14 @@ class TypeConverter(val converter: Converter) {
|
|||||||
|
|
||||||
override fun fromAnnotations(owner: PsiModifierListOwner): Nullability {
|
override fun fromAnnotations(owner: PsiModifierListOwner): Nullability {
|
||||||
val manager = NullableNotNullManager.getInstance(owner.project)
|
val manager = NullableNotNullManager.getInstance(owner.project)
|
||||||
return if (manager.isNotNull(owner, false/* we do not check bases because they are checked by callers of this method*/))
|
return when {
|
||||||
Nullability.NotNull
|
manager.isNotNull(owner, false/* we do not check bases because they are checked by callers of this method*/) ->
|
||||||
else if (manager.isNullable(owner, false))
|
Nullability.NotNull
|
||||||
Nullability.Nullable
|
manager.isNullable(owner, false) ->
|
||||||
else
|
Nullability.Nullable
|
||||||
Nullability.Default
|
else ->
|
||||||
|
Nullability.Default
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun forVariableTypeBeforeUsageSearch(variable: PsiVariable): Nullability {
|
override fun forVariableTypeBeforeUsageSearch(variable: PsiVariable): Nullability {
|
||||||
|
|||||||
@@ -40,17 +40,11 @@ class TypeVisitor(
|
|||||||
|
|
||||||
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
|
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
|
||||||
val name = primitiveType.canonicalText
|
val name = primitiveType.canonicalText
|
||||||
return if (name == "void") {
|
return when {
|
||||||
UnitType()
|
name == "void" -> UnitType()
|
||||||
}
|
PRIMITIVE_TYPES_NAMES.contains(name) -> PrimitiveType(Identifier.withNoPrototype(StringUtil.capitalize(name)))
|
||||||
else if (PRIMITIVE_TYPES_NAMES.contains(name)) {
|
name == "null" -> NullType()
|
||||||
PrimitiveType(Identifier.withNoPrototype(StringUtil.capitalize(name)))
|
else -> PrimitiveType(Identifier.withNoPrototype(name))
|
||||||
}
|
|
||||||
else if (name == "null") {
|
|
||||||
NullType()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PrimitiveType(Identifier.withNoPrototype(name))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,20 +27,16 @@ fun quoteKeywords(packageName: String): String = packageName.split('.').joinToSt
|
|||||||
|
|
||||||
fun getDefaultInitializer(property: Property): Expression? {
|
fun getDefaultInitializer(property: Property): Expression? {
|
||||||
val t = property.type
|
val t = property.type
|
||||||
val result = if (t.isNullable) {
|
val result = when {
|
||||||
LiteralExpression("null")
|
t.isNullable -> LiteralExpression("null")
|
||||||
}
|
t is PrimitiveType -> when (t.name.name) {
|
||||||
else if (t is PrimitiveType) {
|
|
||||||
when (t.name.name) {
|
|
||||||
"Boolean" -> LiteralExpression("false")
|
"Boolean" -> LiteralExpression("false")
|
||||||
"Char" -> LiteralExpression("' '")
|
"Char" -> LiteralExpression("' '")
|
||||||
"Double" -> MethodCallExpression.buildNonNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.DOUBLE.toString())
|
"Double" -> MethodCallExpression.buildNonNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.DOUBLE.toString())
|
||||||
"Float" -> MethodCallExpression.buildNonNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.FLOAT.toString())
|
"Float" -> MethodCallExpression.buildNonNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.FLOAT.toString())
|
||||||
else -> LiteralExpression("0")
|
else -> LiteralExpression("0")
|
||||||
}
|
}
|
||||||
}
|
else -> null
|
||||||
else {
|
|
||||||
null
|
|
||||||
}
|
}
|
||||||
return result?.assignNoPrototype()
|
return result?.assignNoPrototype()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,11 +279,10 @@ class ClassLiteralExpression(val type: Type): Expression() {
|
|||||||
|
|
||||||
fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List<Expression>, needExplicitType: Boolean = true) : MethodCallExpression {
|
fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List<Expression>, needExplicitType: Boolean = true) : MethodCallExpression {
|
||||||
val elementType = arrayType.elementType
|
val elementType = arrayType.elementType
|
||||||
val createArrayFunction = if (elementType is PrimitiveType)
|
val createArrayFunction = when {
|
||||||
(elementType.toNotNullType().canonicalCode() + "ArrayOf").decapitalize()
|
elementType is PrimitiveType -> (elementType.toNotNullType().canonicalCode() + "ArrayOf").decapitalize()
|
||||||
else if (needExplicitType)
|
needExplicitType -> "arrayOf<" + arrayType.elementType.canonicalCode() + ">"
|
||||||
"arrayOf<" + arrayType.elementType.canonicalCode() + ">"
|
else -> "arrayOf"
|
||||||
else
|
}
|
||||||
"arrayOf"
|
|
||||||
return MethodCallExpression.buildNonNull(null, createArrayFunction, ArgumentList.withNoPrototype(initializers))
|
return MethodCallExpression.buildNonNull(null, createArrayFunction, ArgumentList.withNoPrototype(initializers))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,14 +387,10 @@ private class PropertyDetector(
|
|||||||
modifiers.add(Modifier.OVERRIDE)
|
modifiers.add(Modifier.OVERRIDE)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getMethod != null) {
|
when {
|
||||||
modifiers.addIfNotNull(getterModifiers.accessModifier())
|
getMethod != null -> modifiers.addIfNotNull(getterModifiers.accessModifier())
|
||||||
}
|
setMethod != null -> modifiers.addIfNotNull(getterModifiers.accessModifier())
|
||||||
else if (setMethod != null) {
|
else -> modifiers.addIfNotNull(fieldModifiers.accessModifier())
|
||||||
modifiers.addIfNotNull(getterModifiers.accessModifier())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
modifiers.addIfNotNull(fieldModifiers.accessModifier())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val prototypes = listOfNotNull<PsiElement>(field, getMethod, setMethod)
|
val prototypes = listOfNotNull<PsiElement>(field, getMethod, setMethod)
|
||||||
@@ -432,16 +428,20 @@ private class PropertyDetector(
|
|||||||
val superMethod = converter.services.superMethodsSearcher.findDeepestSuperMethods(getOrSetMethod).firstOrNull() ?: return null
|
val superMethod = converter.services.superMethodsSearcher.findDeepestSuperMethods(getOrSetMethod).firstOrNull() ?: return null
|
||||||
|
|
||||||
val containingClass = superMethod.containingClass!!
|
val containingClass = superMethod.containingClass!!
|
||||||
if (converter.inConversionScope(containingClass)) {
|
return when {
|
||||||
val propertyInfo = converter.propertyDetectionCache[containingClass][superMethod]
|
converter.inConversionScope(containingClass) -> {
|
||||||
return if (propertyInfo != null) SuperInfo.Property(propertyInfo.isVar, propertyInfo.name, propertyInfo.modifiers.contains(Modifier.ABSTRACT)) else SuperInfo.Function
|
val propertyInfo = converter.propertyDetectionCache[containingClass][superMethod]
|
||||||
}
|
if (propertyInfo != null) SuperInfo.Property(propertyInfo.isVar, propertyInfo.name, propertyInfo.modifiers.contains(Modifier.ABSTRACT))
|
||||||
else if (superMethod is KtLightMethod) {
|
else SuperInfo.Function
|
||||||
val origin = superMethod.kotlinOrigin
|
}
|
||||||
return if (origin is KtProperty) SuperInfo.Property(origin.isVar, origin.name ?: "", origin.hasModifier(KtTokens.ABSTRACT_KEYWORD)) else SuperInfo.Function
|
superMethod is KtLightMethod -> {
|
||||||
}
|
val origin = superMethod.kotlinOrigin
|
||||||
else {
|
if (origin is KtProperty) SuperInfo.Property(origin.isVar, origin.name ?: "", origin.hasModifier(KtTokens.ABSTRACT_KEYWORD))
|
||||||
return SuperInfo.Function
|
else SuperInfo.Function
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
SuperInfo.Function
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,12 +37,11 @@ class FieldToPropertyProcessing(
|
|||||||
if (field.name != propertyName || replaceReadWithFieldReference || replaceWriteWithFieldReference) MyConvertedCodeProcessor() else null
|
if (field.name != propertyName || replaceReadWithFieldReference || replaceWriteWithFieldReference) MyConvertedCodeProcessor() else null
|
||||||
|
|
||||||
override var javaCodeProcessors =
|
override var javaCodeProcessors =
|
||||||
if (field.hasModifierProperty(PsiModifier.PRIVATE))
|
when {
|
||||||
emptyList()
|
field.hasModifierProperty(PsiModifier.PRIVATE) -> emptyList()
|
||||||
else if (field.name != propertyName)
|
field.name != propertyName -> listOf(ElementRenamedCodeProcessor(propertyName), UseAccessorsJavaCodeProcessor())
|
||||||
listOf(ElementRenamedCodeProcessor(propertyName), UseAccessorsJavaCodeProcessor())
|
else -> listOf(UseAccessorsJavaCodeProcessor())
|
||||||
else
|
}
|
||||||
listOf(UseAccessorsJavaCodeProcessor())
|
|
||||||
|
|
||||||
override val kotlinCodeProcessors =
|
override val kotlinCodeProcessors =
|
||||||
if (field.name != propertyName)
|
if (field.name != propertyName)
|
||||||
|
|||||||
@@ -56,54 +56,50 @@ class Analyzer(private val context: Context) : JsVisitor() {
|
|||||||
|
|
||||||
override fun visitExpressionStatement(x: JsExpressionStatement) {
|
override fun visitExpressionStatement(x: JsExpressionStatement) {
|
||||||
val expression = x.expression
|
val expression = x.expression
|
||||||
if (expression is JsBinaryOperation) {
|
when (expression) {
|
||||||
if (expression.operator == JsBinaryOperator.ASG) {
|
is JsBinaryOperation -> if (expression.operator == JsBinaryOperator.ASG) {
|
||||||
processAssignment(x, expression.arg1, expression.arg2)?.let {
|
processAssignment(x, expression.arg1, expression.arg2)?.let {
|
||||||
// Mark this statement with FQN extracted from assignment.
|
// Mark this statement with FQN extracted from assignment.
|
||||||
// Later, we eliminate such statements if corresponding FQN is reachable
|
// Later, we eliminate such statements if corresponding FQN is reachable
|
||||||
nodeMap[x] = it
|
nodeMap[x] = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
is JsFunction -> expression.name?.let { context.nodes[it]?.original }?.let {
|
||||||
else if (expression is JsFunction) {
|
|
||||||
expression.name?.let { context.nodes[it]?.original }?.let {
|
|
||||||
nodeMap[x] = it
|
nodeMap[x] = it
|
||||||
it.functions += expression
|
it.functions += expression
|
||||||
}
|
}
|
||||||
}
|
is JsInvocation -> {
|
||||||
else if (expression is JsInvocation) {
|
val function = expression.qualifier
|
||||||
val function = expression.qualifier
|
|
||||||
|
|
||||||
// (function(params) { ... })(arguments), assume that params = arguments and walk its body
|
// (function(params) { ... })(arguments), assume that params = arguments and walk its body
|
||||||
if (function is JsFunction) {
|
if (function is JsFunction) {
|
||||||
enterFunction(function, expression.arguments)
|
enterFunction(function, expression.arguments)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// f(arguments), where f is a parameter of outer function and it always receives function() { } as an argument.
|
|
||||||
if (function is JsNameRef && function.qualifier == null) {
|
|
||||||
val postponedFunction = function.name?.let { postponedFunctions[it] }
|
|
||||||
if (postponedFunction != null) {
|
|
||||||
enterFunction(postponedFunction, expression.arguments)
|
|
||||||
invocationsToSkip += expression
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Object.defineProperty()
|
// f(arguments), where f is a parameter of outer function and it always receives function() { } as an argument.
|
||||||
if (context.isObjectDefineProperty(function)) {
|
if (function is JsNameRef && function.qualifier == null) {
|
||||||
handleObjectDefineProperty(x, expression.arguments.getOrNull(0), expression.arguments.getOrNull(1),
|
val postponedFunction = function.name?.let { postponedFunctions[it] }
|
||||||
expression.arguments.getOrNull(2))
|
if (postponedFunction != null) {
|
||||||
}
|
enterFunction(postponedFunction, expression.arguments)
|
||||||
|
invocationsToSkip += expression
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Kotlin.defineModule()
|
// Object.defineProperty()
|
||||||
else if (context.isDefineModule(function)) {
|
when {
|
||||||
// (just remove it)
|
context.isObjectDefineProperty(function) ->
|
||||||
astNodesToEliminate += x
|
handleObjectDefineProperty(x, expression.arguments.getOrNull(0), expression.arguments.getOrNull(1),
|
||||||
}
|
expression.arguments.getOrNull(2))
|
||||||
|
|
||||||
else if (context.isAmdDefine(function)) {
|
// Kotlin.defineModule()
|
||||||
handleAmdDefine(expression, expression.arguments)
|
context.isDefineModule(function) ->
|
||||||
|
// (just remove it)
|
||||||
|
astNodesToEliminate += x
|
||||||
|
context.isAmdDefine(function) ->
|
||||||
|
handleAmdDefine(expression, expression.arguments)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,77 +197,75 @@ class Analyzer(private val context: Context) : JsVisitor() {
|
|||||||
}
|
}
|
||||||
else if (leftNode != null) {
|
else if (leftNode != null) {
|
||||||
// lhs = foo()
|
// lhs = foo()
|
||||||
if (rhs is JsInvocation) {
|
when {
|
||||||
val function = rhs.qualifier
|
rhs is JsInvocation -> {
|
||||||
|
val function = rhs.qualifier
|
||||||
|
|
||||||
// lhs = function(params) { ... }(arguments)
|
// lhs = function(params) { ... }(arguments)
|
||||||
// see corresponding case in visitExpressionStatement
|
// see corresponding case in visitExpressionStatement
|
||||||
if (function is JsFunction) {
|
if (function is JsFunction) {
|
||||||
enterFunction(function, rhs.arguments)
|
enterFunction(function, rhs.arguments)
|
||||||
astNodesToSkip += lhs
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
// lhs = foo(arguments), where foo is a parameter of outer function that always take function literal
|
|
||||||
// see corresponding case in visitExpressionStatement
|
|
||||||
if (function is JsNameRef && function.qualifier == null) {
|
|
||||||
function.name?.let { postponedFunctions[it] }?.let {
|
|
||||||
enterFunction(it, rhs.arguments)
|
|
||||||
astNodesToSkip += lhs
|
astNodesToSkip += lhs
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// lhs = Object.create(constructor)
|
// lhs = foo(arguments), where foo is a parameter of outer function that always take function literal
|
||||||
if (context.isObjectFunction(function, "create")) {
|
// see corresponding case in visitExpressionStatement
|
||||||
// Do not alias lhs and constructor, make unidirectional dependency lhs -> constructor instead.
|
if (function is JsNameRef && function.qualifier == null) {
|
||||||
// Motivation: reachability of a base class does not imply reachability of its derived class
|
function.name?.let { postponedFunctions[it] }?.let {
|
||||||
handleObjectCreate(leftNode, rhs.arguments.getOrNull(0))
|
enterFunction(it, rhs.arguments)
|
||||||
return leftNode
|
astNodesToSkip += lhs
|
||||||
}
|
return null
|
||||||
|
|
||||||
// lhs = Kotlin.defineInlineFunction('fqn', function() { ... })
|
|
||||||
if (context.isDefineInlineFunction(function) && rhs.arguments.size == 2) {
|
|
||||||
leftNode.functions += rhs.arguments[1] as JsFunction
|
|
||||||
val defineInlineFunctionNode = context.extractNode(function)
|
|
||||||
if (defineInlineFunctionNode != null) {
|
|
||||||
leftNode.dependencies += defineInlineFunctionNode
|
|
||||||
}
|
|
||||||
return leftNode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (rhs is JsBinaryOperation) {
|
|
||||||
// Detect lhs = parent.child || (parent.child = {}), which is used to declare packages.
|
|
||||||
// Assume lhs = parent.child
|
|
||||||
if (rhs.operator == JsBinaryOperator.OR) {
|
|
||||||
val secondNode = context.extractNode(rhs.arg1)
|
|
||||||
val reassignment = rhs.arg2
|
|
||||||
if (reassignment is JsBinaryOperation && reassignment.operator == JsBinaryOperator.ASG) {
|
|
||||||
val reassignNode = context.extractNode(reassignment.arg1)
|
|
||||||
val reassignValue = reassignment.arg2
|
|
||||||
if (reassignNode == secondNode && reassignNode != null && reassignValue is JsObjectLiteral &&
|
|
||||||
reassignValue.propertyInitializers.isEmpty()
|
|
||||||
) {
|
|
||||||
return processAssignment(node, lhs, rhs.arg1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lhs = Object.create(constructor)
|
||||||
|
if (context.isObjectFunction(function, "create")) {
|
||||||
|
// Do not alias lhs and constructor, make unidirectional dependency lhs -> constructor instead.
|
||||||
|
// Motivation: reachability of a base class does not imply reachability of its derived class
|
||||||
|
handleObjectCreate(leftNode, rhs.arguments.getOrNull(0))
|
||||||
|
return leftNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// lhs = Kotlin.defineInlineFunction('fqn', function() { ... })
|
||||||
|
if (context.isDefineInlineFunction(function) && rhs.arguments.size == 2) {
|
||||||
|
leftNode.functions += rhs.arguments[1] as JsFunction
|
||||||
|
val defineInlineFunctionNode = context.extractNode(function)
|
||||||
|
if (defineInlineFunctionNode != null) {
|
||||||
|
leftNode.dependencies += defineInlineFunctionNode
|
||||||
|
}
|
||||||
|
return leftNode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
rhs is JsBinaryOperation -> // Detect lhs = parent.child || (parent.child = {}), which is used to declare packages.
|
||||||
else if (rhs is JsFunction) {
|
// Assume lhs = parent.child
|
||||||
// lhs = function() { ... }
|
if (rhs.operator == JsBinaryOperator.OR) {
|
||||||
// During reachability tracking phase: eliminate it if lhs is unreachable, traverse function otherwise
|
val secondNode = context.extractNode(rhs.arg1)
|
||||||
leftNode.functions += rhs
|
val reassignment = rhs.arg2
|
||||||
return leftNode
|
if (reassignment is JsBinaryOperation && reassignment.operator == JsBinaryOperator.ASG) {
|
||||||
}
|
val reassignNode = context.extractNode(reassignment.arg1)
|
||||||
else if (leftNode.qualifier?.memberName == Namer.METADATA) {
|
val reassignValue = reassignment.arg2
|
||||||
// lhs.$metadata$ = expression
|
if (reassignNode == secondNode && reassignNode != null && reassignValue is JsObjectLiteral &&
|
||||||
// During reachability tracking phase: eliminate it if lhs is unreachable, traverse expression
|
reassignValue.propertyInitializers.isEmpty()
|
||||||
// It's commonly used to supply class's metadata
|
) {
|
||||||
leftNode.expressions += rhs
|
return processAssignment(node, lhs, rhs.arg1)
|
||||||
return leftNode
|
}
|
||||||
}
|
}
|
||||||
else if (rhs is JsObjectLiteral && rhs.propertyInitializers.isEmpty()) {
|
}
|
||||||
return leftNode
|
rhs is JsFunction -> {
|
||||||
|
// lhs = function() { ... }
|
||||||
|
// During reachability tracking phase: eliminate it if lhs is unreachable, traverse function otherwise
|
||||||
|
leftNode.functions += rhs
|
||||||
|
return leftNode
|
||||||
|
}
|
||||||
|
leftNode.qualifier?.memberName == Namer.METADATA -> {
|
||||||
|
// lhs.$metadata$ = expression
|
||||||
|
// During reachability tracking phase: eliminate it if lhs is unreachable, traverse expression
|
||||||
|
// It's commonly used to supply class's metadata
|
||||||
|
leftNode.expressions += rhs
|
||||||
|
return leftNode
|
||||||
|
}
|
||||||
|
rhs is JsObjectLiteral && rhs.propertyInitializers.isEmpty() -> return leftNode
|
||||||
}
|
}
|
||||||
|
|
||||||
val nodeInitializedByEmptyObject = extractVariableInitializedByEmptyObject(rhs)
|
val nodeInitializedByEmptyObject = extractVariableInitializedByEmptyObject(rhs)
|
||||||
|
|||||||
@@ -222,15 +222,13 @@ object JsExternalChecker : SimpleDeclarationChecker {
|
|||||||
private fun KtDeclarationWithBody.hasValidExternalBody(bindingContext: BindingContext): Boolean {
|
private fun KtDeclarationWithBody.hasValidExternalBody(bindingContext: BindingContext): Boolean {
|
||||||
if (!hasBody()) return true
|
if (!hasBody()) return true
|
||||||
val body = bodyExpression!!
|
val body = bodyExpression!!
|
||||||
return if (!hasBlockBody()) {
|
return when {
|
||||||
body.isDefinedExternallyExpression(bindingContext)
|
!hasBlockBody() -> body.isDefinedExternallyExpression(bindingContext)
|
||||||
}
|
body is KtBlockExpression -> {
|
||||||
else if (body is KtBlockExpression) {
|
val statement = body.statements.singleOrNull() ?: return false
|
||||||
val statement = body.statements.singleOrNull() ?: return false
|
statement.isDefinedExternallyExpression(bindingContext)
|
||||||
statement.isDefinedExternallyExpression(bindingContext)
|
}
|
||||||
}
|
else -> false
|
||||||
else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-9
@@ -66,15 +66,17 @@ class RedundantStatementElimination(private val root: JsFunction) {
|
|||||||
private fun replace(expression: JsExpression): List<JsExpression> {
|
private fun replace(expression: JsExpression): List<JsExpression> {
|
||||||
return when (expression) {
|
return when (expression) {
|
||||||
is JsNameRef -> {
|
is JsNameRef -> {
|
||||||
if (expression.name in localVars) {
|
when {
|
||||||
listOf()
|
expression.name in localVars -> {
|
||||||
}
|
listOf()
|
||||||
else if (expression.sideEffects != SideEffectKind.AFFECTS_STATE) {
|
}
|
||||||
val qualifier = expression.qualifier
|
expression.sideEffects != SideEffectKind.AFFECTS_STATE -> {
|
||||||
if (qualifier != null) replace(qualifier) else listOf()
|
val qualifier = expression.qualifier
|
||||||
}
|
if (qualifier != null) replace(qualifier) else listOf()
|
||||||
else {
|
}
|
||||||
listOf(expression)
|
else -> {
|
||||||
|
listOf(expression)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-25
@@ -190,35 +190,27 @@ object Constants {
|
|||||||
private fun formatChar(c: Char) = '\'' + quote(c) + '\''
|
private fun formatChar(c: Char) = '\'' + quote(c) + '\''
|
||||||
private fun formatString(s: String) = '"' + quote(s) + '"'
|
private fun formatString(s: String) = '"' + quote(s) + '"'
|
||||||
|
|
||||||
private fun formatFloat(f: Float): String {
|
private fun formatFloat(f: Float): String = when {
|
||||||
if (java.lang.Float.isNaN(f))
|
java.lang.Float.isNaN(f) -> "0.0f/0.0f"
|
||||||
return "0.0f/0.0f"
|
java.lang.Float.isInfinite(f) -> if (f < 0) "-1.0f/0.0f" else "1.0f/0.0f"
|
||||||
else if (java.lang.Float.isInfinite(f))
|
else -> "${f}f"
|
||||||
return if (f < 0) "-1.0f/0.0f" else "1.0f/0.0f"
|
|
||||||
else
|
|
||||||
return "${f}f"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatDouble(d: Double): String {
|
private fun formatDouble(d: Double): String = when {
|
||||||
if (java.lang.Double.isNaN(d))
|
java.lang.Double.isNaN(d) -> "0.0/0.0"
|
||||||
return "0.0/0.0"
|
java.lang.Double.isInfinite(d) -> if (d < 0) "-1.0/0.0" else "1.0/0.0"
|
||||||
else if (java.lang.Double.isInfinite(d))
|
else -> d.toString()
|
||||||
return if (d < 0) "-1.0/0.0" else "1.0/0.0"
|
|
||||||
else
|
|
||||||
return d.toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun quote(ch: Char): String {
|
fun quote(ch: Char): String = when (ch) {
|
||||||
return when (ch) {
|
'\b' -> "\\b"
|
||||||
'\b' -> "\\b"
|
'\n' -> "\\n"
|
||||||
'\n' -> "\\n"
|
'\r' -> "\\r"
|
||||||
'\r' -> "\\r"
|
'\t' -> "\\t"
|
||||||
'\t' -> "\\t"
|
'\'' -> "\\'"
|
||||||
'\'' -> "\\'"
|
'\"' -> "\\\""
|
||||||
'\"' -> "\\\""
|
'\\' -> "\\\\"
|
||||||
'\\' -> "\\\\"
|
else -> if (isPrintableAscii(ch)) ch.toString() else String.format("\\u%04x", ch.toInt())
|
||||||
else -> if (isPrintableAscii(ch)) ch.toString() else String.format("\\u%04x", ch.toInt())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun quote(s: String): String {
|
fun quote(s: String): String {
|
||||||
|
|||||||
+4
-6
@@ -95,12 +95,10 @@ class KotlinTypes(
|
|||||||
if (extendsBound != null && extendsBound !is JePsiType) illegalArg("extendsBound should have PsiType")
|
if (extendsBound != null && extendsBound !is JePsiType) illegalArg("extendsBound should have PsiType")
|
||||||
if (superBound != null && superBound !is JePsiType) illegalArg("superBound should have PsiType")
|
if (superBound != null && superBound !is JePsiType) illegalArg("superBound should have PsiType")
|
||||||
|
|
||||||
return JeWildcardType(if (extendsBound != null) {
|
return JeWildcardType(when {
|
||||||
PsiWildcardType.createExtends(psiManager(), (extendsBound as JePsiType).psiType)
|
extendsBound != null -> PsiWildcardType.createExtends(psiManager(), (extendsBound as JePsiType).psiType)
|
||||||
} else if (superBound != null) {
|
superBound != null -> PsiWildcardType.createSuper(psiManager(), (superBound as JePsiType).psiType)
|
||||||
PsiWildcardType.createSuper(psiManager(), (superBound as JePsiType).psiType)
|
else -> PsiWildcardType.createUnbounded(psiManager())
|
||||||
} else {
|
|
||||||
PsiWildcardType.createUnbounded(psiManager())
|
|
||||||
}, isRaw = false)
|
}, isRaw = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-10
@@ -80,16 +80,13 @@ class SuppressLintIntentionAction(val id: String, val element: PsiElement) : Int
|
|||||||
val args = entry.valueArgumentList
|
val args = entry.valueArgumentList
|
||||||
val psiFactory = KtPsiFactory(entry)
|
val psiFactory = KtPsiFactory(entry)
|
||||||
val newArgList = psiFactory.createCallArguments("($argument)")
|
val newArgList = psiFactory.createCallArguments("($argument)")
|
||||||
if (args == null) {
|
when {
|
||||||
// new argument list
|
args == null -> // new argument list
|
||||||
entry.addAfter(newArgList, entry.lastChild)
|
entry.addAfter(newArgList, entry.lastChild)
|
||||||
}
|
args.arguments.isEmpty() -> // replace '()' with a new argument list
|
||||||
else if (args.arguments.isEmpty()) {
|
args.replace(newArgList)
|
||||||
// replace '()' with a new argument list
|
args.arguments.none { it.textMatches(argument) } ->
|
||||||
args.replace(newArgList)
|
args.addArgument(newArgList.arguments[0])
|
||||||
}
|
|
||||||
else if (args.arguments.none { it.textMatches(argument) }) {
|
|
||||||
args.addArgument(newArgList.arguments[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -286,15 +286,16 @@ internal object KotlinConverter {
|
|||||||
is KtVariableDeclaration -> expr<UDeclarationsExpression>(build(::convertVariablesDeclaration))
|
is KtVariableDeclaration -> expr<UDeclarationsExpression>(build(::convertVariablesDeclaration))
|
||||||
|
|
||||||
is KtStringTemplateExpression -> {
|
is KtStringTemplateExpression -> {
|
||||||
if (expression.entries.isEmpty()) {
|
when {
|
||||||
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
|
expression.entries.isEmpty() -> {
|
||||||
expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, parent, "") }
|
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
|
||||||
}
|
expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, parent, "") }
|
||||||
else if (expression.entries.size == 1)
|
}
|
||||||
convertEntry(expression.entries[0], parentCallback, requiredType)
|
expression.entries.size == 1 -> convertEntry(expression.entries[0], parentCallback, requiredType)
|
||||||
else {
|
else -> {
|
||||||
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
|
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
|
||||||
expr<UExpression> { KotlinStringTemplateUPolyadicExpression(expression, parent) }
|
expr<UExpression> { KotlinStringTemplateUPolyadicExpression(expression, parent) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
|
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
|
||||||
|
|||||||
Reference in New Issue
Block a user