diff --git a/.gitignore b/.gitignore index 7922f383f52..dfa683f4a2c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ out pluginPublisher/idea* pluginPublisher/plugin-verifier.jar tmp -workspace.xml \ No newline at end of file +workspace.xml +*.versionsBackup diff --git a/.idea/libraries/java_i18n.xml b/.idea/libraries/java_i18n.xml new file mode 100644 index 00000000000..21e5c7eb971 --- /dev/null +++ b/.idea/libraries/java_i18n.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/properties.xml b/.idea/libraries/properties.xml new file mode 100644 index 00000000000..59a7ec62ded --- /dev/null +++ b/.idea/libraries/properties.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/testng_plugin.xml b/.idea/libraries/testng_plugin.xml new file mode 100644 index 00000000000..cacf809be54 --- /dev/null +++ b/.idea/libraries/testng_plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/build.xml b/build.xml index a0ea4b8d843..8ffd4fa6ac8 100644 --- a/build.xml +++ b/build.xml @@ -354,6 +354,8 @@ -dontwarn com.intellij.util.ui.IsRetina* -dontwarn com.intellij.util.RetinaImage* + -dontwarn apple.awt.* + -dontwarn dk.brics.automaton.* -dontwarn org.fusesource.** -libraryjars '${rtjar}' @@ -573,4 +575,4 @@ - \ No newline at end of file + diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java index 255b476a9de..f5b1f42c35a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.codegen; +import com.intellij.openapi.progress.ProcessCanceledException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.context.ClassContext; @@ -54,6 +55,9 @@ public class MemberCodegen extends GenerationStateAware { try { functionCodegen.gen((JetNamedFunction) functionOrProperty); } + catch (ProcessCanceledException e) { + throw e; + } catch (CompilationException e) { throw e; } @@ -65,6 +69,9 @@ public class MemberCodegen extends GenerationStateAware { try { new PropertyCodegen(context, classBuilder, functionCodegen, this).gen((JetProperty) functionOrProperty); } + catch (ProcessCanceledException e) { + throw e; + } catch (CompilationException e) { throw e; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index cb1dbc1145a..cd7427c4c2b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -219,7 +219,7 @@ public class JetTypeMapper extends BindingTraceAware { @NotNull public Type mapType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode kind) { - return mapType(jetType, signatureVisitor, kind, Variance.INVARIANT); + return mapType(jetType, signatureVisitor, kind, Variance.INVARIANT, false); } @NotNull @@ -227,7 +227,17 @@ public class JetTypeMapper extends BindingTraceAware { @NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode kind, - @NotNull Variance howThisTypeIsUsed + @NotNull Variance howThisTypeIsUsed) { + return mapType(jetType, signatureVisitor, kind, howThisTypeIsUsed, false); + } + + @NotNull + public Type mapType( + @NotNull JetType jetType, + @Nullable BothSignatureWriter signatureVisitor, + @NotNull JetTypeMapperMode kind, + @NotNull Variance howThisTypeIsUsed, + boolean arrayParameter ) { Type known = null; DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); @@ -243,7 +253,7 @@ public class JetTypeMapper extends BindingTraceAware { return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed); } else if (kind == JetTypeMapperMode.TYPE_PARAMETER) { - return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed); + return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, arrayParameter); } else if (kind == JetTypeMapperMode.TRAIT_IMPL) { throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType); @@ -291,7 +301,7 @@ public class JetTypeMapper extends BindingTraceAware { if (signatureVisitor != null) { signatureVisitor.writeArrayType(jetType.isNullable(), memberProjection.getProjectionKind()); - mapType(memberType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); + mapType(memberType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER, memberProjection.getProjectionKind(), true); signatureVisitor.writeArrayEnd(); } @@ -408,10 +418,24 @@ public class JetTypeMapper extends BindingTraceAware { Type asmType, @Nullable BothSignatureWriter signatureVisitor, @NotNull Variance howThisTypeIsUsed + ) { + return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, false); + } + + private Type mapKnownAsmType( + JetType jetType, + Type asmType, + @Nullable BothSignatureWriter signatureVisitor, + @NotNull Variance howThisTypeIsUsed, + boolean arrayParameter ) { if (signatureVisitor != null) { if (jetType.getArguments().isEmpty()) { - String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType); + if (arrayParameter + && (howThisTypeIsUsed == Variance.IN_VARIANCE)) { + asmType = AsmTypeConstants.OBJECT_TYPE; + } + String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType, arrayParameter); signatureVisitor.writeAsmType(asmType, jetType.isNullable(), kotlinTypeName); } else { @@ -424,12 +448,18 @@ public class JetTypeMapper extends BindingTraceAware { @Nullable private static String getKotlinTypeNameForSignature(@NotNull JetType jetType, @NotNull Type asmType) { + return getKotlinTypeNameForSignature(jetType, asmType, false); + } + + @Nullable + private static String getKotlinTypeNameForSignature(@NotNull JetType jetType, @NotNull Type asmType, boolean arrayParameter) { ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); if (descriptor == null) return null; if (asmType.getSort() != Type.OBJECT) return null; JvmClassName jvmClassName = JvmClassName.byType(asmType); - if (JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmClassName.getFqName()).size() > 1) { + if ((arrayParameter && JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmClassName.getFqName()).size() >= 1) + || ((!arrayParameter) && JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmClassName.getFqName()).size() > 1)) { return JvmClassName.byClassDescriptor(descriptor).getSignatureName(); } return null; diff --git a/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition b/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition new file mode 100644 index 00000000000..6953a3b18db --- /dev/null +++ b/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition @@ -0,0 +1 @@ +org.jetbrains.jet.lang.resolve.java.sam.SamAdapterOverridabilityCondition diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index 3e7255de471..5bd5219e9d9 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -38,6 +38,7 @@ import java.util.List; import java.util.Set; import static org.jetbrains.jet.lang.resolve.java.TypeUsage.*; +import static org.jetbrains.jet.lang.types.Variance.*; public class JavaTypeTransformer { @@ -73,7 +74,7 @@ public class JavaTypeTransformer { if (!wildcardType.isBounded()) { return SubstitutionUtils.makeStarProjection(typeParameterDescriptor); } - Variance variance = wildcardType.isExtends() ? Variance.OUT_VARIANCE : Variance.IN_VARIANCE; + Variance variance = wildcardType.isExtends() ? OUT_VARIANCE : IN_VARIANCE; PsiType bound = wildcardType.getBound(); assert bound != null; @@ -165,14 +166,18 @@ public class JavaTypeTransformer { List parameters = classData.getTypeConstructor().getParameters(); if (isRaw(classType, !parameters.isEmpty())) { for (TypeParameterDescriptor parameter : parameters) { - TypeProjection starProjection = SubstitutionUtils.makeStarProjection(parameter); - if (howThisTypeIsUsed == SUPERTYPE) { - // projections are not allowed in immediate arguments of supertypes - arguments.add(new TypeProjection(starProjection.getType())); - } - else { - arguments.add(starProjection); - } + // not making a star projection because of this case: + // Java: + // class C {} + // The upper bound is raw here, and we can't compute the projection: it would be infinite: + // C<*> = C>> + // this way we loose some type information, even when the case is not so bad, but it doesn't seem to matter + + // projections are not allowed in immediate arguments of supertypes + Variance projectionKind = parameter.getVariance() == OUT_VARIANCE || howThisTypeIsUsed == SUPERTYPE + ? INVARIANT + : OUT_VARIANCE; + arguments.add(new TypeProjection(projectionKind, KotlinBuiltIns.getInstance().getNullableAnyType())); } } else { @@ -198,7 +203,7 @@ public class JavaTypeTransformer { if (typeProjection.getProjectionKind() == typeParameterDescriptor.getVariance()) { // remove redundant 'out' and 'in' - arguments.add(new TypeProjection(Variance.INVARIANT, typeProjection.getType())); + arguments.add(new TypeProjection(INVARIANT, typeProjection.getType())); } else { arguments.add(typeProjection); @@ -245,10 +250,10 @@ public class JavaTypeTransformer { private Variance arrayElementTypeProjectionKind(boolean vararg) { Variance variance; if (howThisTypeIsUsed == MEMBER_SIGNATURE_CONTRAVARIANT && !vararg) { - variance = Variance.OUT_VARIANCE; + variance = OUT_VARIANCE; } else { - variance = Variance.INVARIANT; + variance = INVARIANT; } return variance; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SamAdapterOverridabilityCondition.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SamAdapterOverridabilityCondition.java new file mode 100644 index 00000000000..c86cbbd7746 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SamAdapterOverridabilityCondition.java @@ -0,0 +1,100 @@ +package org.jetbrains.jet.lang.resolve.java.sam; + +import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; +import org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeSubstitutor; +import org.jetbrains.jet.lang.types.TypeUtils; + +import java.util.List; + +public class SamAdapterOverridabilityCondition implements ExternalOverridabilityCondition { + @Override + public boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { + if (subDescriptor instanceof PropertyDescriptor) { + return true; + } + + SimpleFunctionDescriptor superOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) superDescriptor); + SimpleFunctionDescriptor subOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) subDescriptor); + if (superOriginal == null || subOriginal == null) { // super or sub is/overrides DECLARATION + return subOriginal == null; // DECLARATION can override anything + } + + // inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure + return equalErasure(superOriginal, subOriginal); + } + + private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) { + List parameters1 = fun1.getValueParameters(); + List parameters2 = fun2.getValueParameters(); + + for (ValueParameterDescriptor param1 : parameters1) { + ValueParameterDescriptor param2 = parameters2.get(param1.getIndex()); + if (!TypeUtils.equalClasses(param2.getType(), param1.getType())) { + return false; + } + } + return true; + } + + // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters + @Nullable + private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) { + DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration(); + if (!(containingDeclaration instanceof ClassDescriptor)) { + return null; + } + Pair declarationOrSynthesized = + getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType()); + + if (declarationOrSynthesized == null) { + return null; + } + + SimpleFunctionDescriptor fun = declarationOrSynthesized.first; + if (fun.getKind() != CallableMemberDescriptor.Kind.SYNTHESIZED) { + return null; + } + + SimpleFunctionDescriptor originalOfSynthesized = ((SimpleFunctionDescriptorImpl) fun.getOriginal()) + .getOriginalOfSynthesized(); + if (originalOfSynthesized == null) { + return null; + } + + return ((SimpleFunctionDescriptor) originalOfSynthesized.substitute(TypeSubstitutor.create(declarationOrSynthesized.second))); + } + + @Nullable + private static Pair getNearestDeclarationOrSynthesized( + @NotNull SimpleFunctionDescriptor samAdapter, + @NotNull JetType ownerType + ) { + if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + return Pair.create(samAdapter, ownerType); + } + for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) { + ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration(); + + for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) { + if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) { + continue; + } + + Pair found = + getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype); + if (found != null) { + return found; + } + } + + } + return null; + } + +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java index ed9122d5327..281fa655c5e 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java @@ -45,9 +45,7 @@ public class SingleAbstractMethodUtils { public static List getAbstractMembers(@NotNull JetType type) { List abstractMembers = Lists.newArrayList(); for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) { - if (member instanceof CallableMemberDescriptor && - ((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT && - !CallResolverUtil.isOrOverridesSynthesized((CallableMemberDescriptor) member)) { + if (member instanceof CallableMemberDescriptor && ((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT) { abstractMembers.add((CallableMemberDescriptor) member); } } @@ -190,7 +188,8 @@ public class SingleAbstractMethodUtils { original.getContainingDeclaration(), original.getAnnotations(), original.getName(), - CallableMemberDescriptor.Kind.SYNTHESIZED + CallableMemberDescriptor.Kind.SYNTHESIZED, + original ); FunctionInitializer initializer = new FunctionInitializer() { @Override @@ -205,7 +204,7 @@ public class SingleAbstractMethodUtils { typeParameters, valueParameters, returnType, - original.getModality(), + Modality.FINAL, original.getVisibility(), false ); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java index e04e6618a52..eac3c82898e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java @@ -30,12 +30,29 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme private boolean isInline = false; + private final SimpleFunctionDescriptor originalOfSynthesized; // TODO replace with user data + public SimpleFunctionDescriptorImpl( @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @NotNull Name name, - @NotNull Kind kind) { + @NotNull Kind kind + ) { + this(containingDeclaration, annotations, name, kind, null); + } + + public SimpleFunctionDescriptorImpl( + @NotNull DeclarationDescriptor containingDeclaration, + @NotNull List annotations, + @NotNull Name name, + @NotNull Kind kind, + @Nullable SimpleFunctionDescriptor originalOfSynthesized + ) { super(containingDeclaration, annotations, name, kind); + this.originalOfSynthesized = originalOfSynthesized; + if (originalOfSynthesized != null) { + assert kind == Kind.SYNTHESIZED; + } } private SimpleFunctionDescriptorImpl( @@ -45,6 +62,7 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme @NotNull Name name, @NotNull Kind kind) { super(containingDeclaration, original, annotations, name, kind); + originalOfSynthesized = null; } public SimpleFunctionDescriptorImpl initialize( @@ -100,4 +118,10 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme public boolean isInline() { return isInline; } + + // TODO replace with user data + @Nullable + public SimpleFunctionDescriptor getOriginalOfSynthesized() { + return originalOfSynthesized; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 7fb709deed9..691836bc753 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -214,7 +214,14 @@ public class JetExpressionParsing extends AbstractJetParsing { } } - public static final TokenSet ALLOW_NEWLINE_OPERATIONS = TokenSet.create(DOT, SAFE_ACCESS); + public static final TokenSet ALLOW_NEWLINE_OPERATIONS = TokenSet.create( + DOT, SAFE_ACCESS, + COLON, AS_KEYWORD, AS_SAFE, + ELVIS, + // Can't allow `is` and `!is` because of when entry conditions: IS_KEYWORD, NOT_IS, + ANDAND, + OROR + ); public static final TokenSet ALL_OPERATIONS; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java index 9109d52cc7b..963e37911d4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.psi; import com.google.common.collect.Lists; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; @@ -62,6 +63,11 @@ public class JetModifierList extends JetElementImpl { return getModifierNode(token) != null; } + @Nullable + public PsiElement getModifier(JetToken token) { + return findChildByType(token); + } + @Nullable public ASTNode getModifierNode(JetToken token) { ASTNode node = getNode().getFirstChildNode(); @@ -71,4 +77,6 @@ public class JetModifierList extends JetElementImpl { } return null; } + + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ExternalOverridabilityCondition.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ExternalOverridabilityCondition.java new file mode 100644 index 00000000000..17dd911ba1b --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ExternalOverridabilityCondition.java @@ -0,0 +1,8 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; + +public interface ExternalOverridabilityCondition { + boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/MemberComparator.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/MemberComparator.java index 09eecdc7a51..e4c783c81e5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/MemberComparator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/MemberComparator.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.renderer.DescriptorRenderer; +import org.jetbrains.jet.renderer.DescriptorRendererBuilder; import java.util.Comparator; import java.util.List; @@ -25,6 +26,8 @@ import java.util.List; public class MemberComparator implements Comparator { public static final MemberComparator INSTANCE = new MemberComparator(); + private static final DescriptorRenderer RENDERER = new DescriptorRendererBuilder().setWithDefinedIn(false).setVerbose(true).build(); + private MemberComparator() { } @@ -77,8 +80,8 @@ public class MemberComparator implements Comparator { ReceiverParameterDescriptor c2ReceiverParameter = c2.getReceiverParameter(); assert (c1ReceiverParameter != null) == (c2ReceiverParameter != null); if (c1ReceiverParameter != null) { - String r1 = DescriptorRenderer.TEXT.renderType(c1ReceiverParameter.getType()); - String r2 = DescriptorRenderer.TEXT.renderType(c2ReceiverParameter.getType()); + String r1 = RENDERER.renderType(c1ReceiverParameter.getType()); + String r2 = RENDERER.renderType(c2ReceiverParameter.getType()); int receiversCompareTo = r1.compareTo(r2); if (receiversCompareTo != 0) { return receiversCompareTo; @@ -88,8 +91,8 @@ public class MemberComparator implements Comparator { List c1ValueParameters = c1.getValueParameters(); List c2ValueParameters = c2.getValueParameters(); for (int i = 0; i < Math.min(c1ValueParameters.size(), c2ValueParameters.size()); i++) { - String p1 = DescriptorRenderer.TEXT.renderType(c1ValueParameters.get(i).getType()); - String p2 = DescriptorRenderer.TEXT.renderType(c2ValueParameters.get(i).getType()); + String p1 = RENDERER.renderType(c1ValueParameters.get(i).getType()); + String p2 = RENDERER.renderType(c2ValueParameters.get(i).getType()); int parametersCompareTo = p1.compareTo(p2); if (parametersCompareTo != 0) { return parametersCompareTo; @@ -104,8 +107,8 @@ public class MemberComparator implements Comparator { List c1TypeParameters = c1.getTypeParameters(); List c2TypeParameters = c2.getTypeParameters(); for (int i = 0; i < Math.min(c1TypeParameters.size(), c2TypeParameters.size()); i++) { - String p1 = DescriptorRenderer.TEXT.renderType(c1TypeParameters.get(i).getUpperBoundsAsType()); - String p2 = DescriptorRenderer.TEXT.renderType(c2TypeParameters.get(i).getUpperBoundsAsType()); + String p1 = RENDERER.renderType(c1TypeParameters.get(i).getUpperBoundsAsType()); + String p2 = RENDERER.renderType(c2TypeParameters.get(i).getUpperBoundsAsType()); int parametersCompareTo = p1.compareTo(p2); if (parametersCompareTo != 0) { return parametersCompareTo; @@ -120,9 +123,12 @@ public class MemberComparator implements Comparator { if (c1 instanceof CallableMemberDescriptor && c2 instanceof CallableMemberDescriptor) { CallableMemberDescriptor.Kind c1Kind = ((CallableMemberDescriptor) c1).getKind(); CallableMemberDescriptor.Kind c2Kind = ((CallableMemberDescriptor) c2).getKind(); - return c1Kind.ordinal() - c2Kind.ordinal(); + int kindsCompareTo = c1Kind.ordinal() - c2Kind.ordinal(); + if (kindsCompareTo != 0) { + return kindsCompareTo; + } } - return 0; + return RENDERER.render(o1).compareTo(RENDERER.render(o2)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 1a88347c6c5..b26c09a6a6f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -43,6 +43,7 @@ import javax.inject.Inject; import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; +import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT; import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; public class OverrideResolver { @@ -242,13 +243,47 @@ public class OverrideResolver { Queue fromSuperQueue = new LinkedList(notOverridden); while (!fromSuperQueue.isEmpty()) { CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtil.findMemberWithMaxVisibility(fromSuperQueue); - Collection overridables = extractMembersOverridableBy(notOverriddenFromSuper, fromSuperQueue, sink); - createAndBindFakeOverride(notOverriddenFromSuper, overridables, current, sink); + Collection overridables = extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, + sink); + createAndBindFakeOverride(overridables, current, sink); } } + private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) { + if (a instanceof SimpleFunctionDescriptor) { + assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass(); + + JetType aReturnType = a.getReturnType(); + assert aReturnType != null; + JetType bReturnType = b.getReturnType(); + assert bReturnType != null; + + return JetTypeChecker.INSTANCE.isSubtypeOf(aReturnType, bReturnType); + } + if (a instanceof PropertyDescriptor) { + assert b instanceof PropertyDescriptor : "b is " + b.getClass(); + + if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) { + return ((PropertyDescriptor) a).isVar(); + } + + // both vals + return JetTypeChecker.INSTANCE.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType()); + } + throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); + } + + private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection overridables) { + CallableMemberDescriptor result = null; + for (CallableMemberDescriptor overridable : overridables) { + if (result == null || isMoreSpecific(overridable, result)) { + result = overridable; + } + } + return result; + } + private static void createAndBindFakeOverride( - @NotNull CallableMemberDescriptor notOverriddenFromSuper, @NotNull Collection overridables, @NotNull ClassDescriptor current, @NotNull DescriptorSink sink @@ -258,8 +293,9 @@ public class OverrideResolver { boolean allInvisible = visibleOverridables.isEmpty(); Collection effectiveOverridden = allInvisible ? overridables : visibleOverridables; Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; + CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden); CallableMemberDescriptor fakeOverride = - notOverriddenFromSuper.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); + mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); for (CallableMemberDescriptor descriptor : effectiveOverridden) { OverridingUtil.bindOverride(fakeOverride, descriptor); } @@ -292,7 +328,7 @@ public class OverrideResolver { } @NotNull - private static Collection extractMembersOverridableBy( + private static Collection extractMembersOverridableInBothWays( @NotNull CallableMemberDescriptor overrider, @NotNull Queue extractFrom, @NotNull DescriptorSink sink @@ -306,19 +342,17 @@ public class OverrideResolver { continue; } - OverridingUtil.OverrideCompatibilityInfo.Result result = + OverridingUtil.OverrideCompatibilityInfo.Result result1 = OverridingUtil.isOverridableBy(candidate, overrider).getResult(); - switch (result) { - case OVERRIDABLE: - overridable.add(candidate); - iterator.remove(); - break; - case CONFLICT: - sink.conflict(overrider, candidate); - iterator.remove(); - break; - case INCOMPATIBLE: - break; + OverridingUtil.OverrideCompatibilityInfo.Result result2 = + OverridingUtil.isOverridableBy(overrider, candidate).getResult(); + if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) { + overridable.add(candidate); + iterator.remove(); + } + else if (result1 == CONFLICT || result2 == CONFLICT) { + sink.conflict(overrider, candidate); + iterator.remove(); } } return overridable; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index 05b614c73d7..ec6a001deed 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -21,6 +21,7 @@ import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -31,6 +32,12 @@ import java.util.*; public class OverridingUtil { + private static final List EXTERNAL_CONDITIONS = + ContainerUtil.collect(ServiceLoader.load( + ExternalOverridabilityCondition.class, + ExternalOverridabilityCondition.class.getClassLoader()).iterator() + ); + private OverridingUtil() { } @@ -128,7 +135,7 @@ public class OverridingUtil { // TODO : Visibility if ((superDescriptor.getReceiverParameter() == null) != (subDescriptor.getReceiverParameter() == null)) { - return OverrideCompatibilityInfo.receiverPresenseMismatch(); + return OverrideCompatibilityInfo.receiverPresenceMismatch(); } if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) { @@ -183,6 +190,11 @@ public class OverridingUtil { } } + for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) { + if (!externalCondition.isOverridable(superDescriptor, subDescriptor)) { + return OverrideCompatibilityInfo.externalConditionFailed(externalCondition.getClass()); + } + } } else { @@ -277,7 +289,7 @@ public class OverridingUtil { } else { if (descriptor.getOverriddenDescriptors().isEmpty()) { - throw new IllegalStateException(); + throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor); } for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) { getOverriddenDeclarations(overridden, r); @@ -322,8 +334,8 @@ public class OverridingUtil { } @NotNull - public static OverrideCompatibilityInfo receiverPresenseMismatch() { - return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "receiverPresenseMismatch"); // TODO + public static OverrideCompatibilityInfo receiverPresenceMismatch() { + return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "receiverPresenceMismatch"); // TODO } @NotNull @@ -356,6 +368,11 @@ public class OverridingUtil { return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "varOverriddenByVal"); // TODO } + @NotNull + public static OverrideCompatibilityInfo externalConditionFailed(Class conditionClass) { + return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "externalConditionFailed: " + conditionClass.getName()); // TODO + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// private final Result overridable; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java index 243f30baab7..91d179bd635 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java @@ -20,13 +20,11 @@ import gnu.trove.THashSet; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; -import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; +import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; @@ -58,21 +56,52 @@ public class OverloadingConflictResolver { return object == null ? 0 : object.getResultingDescriptor().hashCode(); } }); - meLoop: for (ResolvedCallWithTrace candidateCall : candidates) { - D me = candidateCall.getResultingDescriptor(); - for (ResolvedCallWithTrace otherCall : candidates) { - D other = otherCall.getResultingDescriptor(); - if (other == me) continue; - if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) { - continue meLoop; - } + if (isMaximallySpecific(candidateCall, candidates, discriminateGenericDescriptors)) { + maximallySpecific.add(candidateCall); } - maximallySpecific.add(candidateCall); } return maximallySpecific.size() == 1 ? maximallySpecific.iterator().next() : null; } + private boolean isMaximallySpecific( + @NotNull ResolvedCallWithTrace candidateCall, + @NotNull Set> candidates, + boolean discriminateGenericDescriptors + ) { + D me = candidateCall.getResultingDescriptor(); + + boolean isInvoke = candidateCall instanceof VariableAsFunctionResolvedCall; + VariableDescriptor variable; + if (isInvoke) { + variable = ((VariableAsFunctionResolvedCall) candidateCall).getVariableCall().getResultingDescriptor(); + } + else { + variable = null; + } + + for (ResolvedCallWithTrace otherCall : candidates) { + D other = otherCall.getResultingDescriptor(); + if (other == me) continue; + + if (definitelyNotMaximallySpecific(me, other, discriminateGenericDescriptors)) { + + if (!isInvoke) return false; + + assert otherCall instanceof VariableAsFunctionResolvedCall : "'invoke' candidate goes with usual one: " + candidateCall + otherCall; + ResolvedCallWithTrace otherVariableCall = ((VariableAsFunctionResolvedCall) otherCall).getVariableCall(); + if (definitelyNotMaximallySpecific(variable, otherVariableCall.getResultingDescriptor(), discriminateGenericDescriptors)) { + return false; + } + } + } + return true; + } + + private boolean definitelyNotMaximallySpecific(D me, D other, boolean discriminateGenericDescriptors) { + return !moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors); + } + /** * Let < mean "more specific" * Subtype < supertype diff --git a/compiler/testData/builtin-classes.txt b/compiler/testData/builtin-classes.txt index 1082314e80a..d06a3f528ac 100644 --- a/compiler/testData/builtin-classes.txt +++ b/compiler/testData/builtin-classes.txt @@ -1323,7 +1323,7 @@ public trait MutableList : jet.List, jet.MutableCollection { public abstract override /*2*/ /*fake_override*/ fun hashCode(): jet.Int public abstract override /*1*/ /*fake_override*/ fun indexOf(/*0*/ o: jet.Any?): jet.Int public abstract override /*2*/ /*fake_override*/ fun isEmpty(): jet.Boolean - public abstract override /*2*/ /*fake_override*/ fun iterator(): jet.Iterator + public abstract override /*2*/ /*fake_override*/ fun iterator(): jet.MutableIterator public abstract override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: jet.Any?): jet.Int public abstract override /*1*/ fun listIterator(): jet.MutableListIterator public abstract override /*1*/ fun listIterator(/*0*/ index: jet.Int): jet.MutableListIterator diff --git a/compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapterInKotlin.java b/compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapterInKotlin.java deleted file mode 100644 index 60f0119ff89..00000000000 --- a/compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapterInKotlin.java +++ /dev/null @@ -1,7 +0,0 @@ -class Super { - public String lastCalled = null; - - void foo(Runnable r) { - lastCalled = "super"; - } -} diff --git a/compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapterInKotlin.kt b/compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapterInKotlin.kt deleted file mode 100644 index 684e527cf72..00000000000 --- a/compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapterInKotlin.kt +++ /dev/null @@ -1,21 +0,0 @@ -class Sub() : Super() { - override fun foo(r : (() -> Unit)?) { - lastCalled = "sub" - } -} - -fun box(): String { - val sub = Sub() - - (sub : Super).foo{ } - if (sub.lastCalled != "super") { - return "FAIL: ${sub.lastCalled} instead of super" - } - - sub.foo{ } - if (sub.lastCalled != "sub") { - return "FAIL: ${sub.lastCalled} instead of sub" - } - - return "OK" -} diff --git a/compiler/testData/codegen/boxWithStdlib/arrays/kt3771.kt b/compiler/testData/codegen/boxWithStdlib/arrays/kt3771.kt new file mode 100644 index 00000000000..9341b533e86 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/arrays/kt3771.kt @@ -0,0 +1,14 @@ +fun fill(dest : Array, v : String) { + dest[0] = v +} + +fun box() : String { +//fun main(args : Array) { + val s : String = "bar" + val any : Array = array(1, "foo", 1.234) + fill(any, s) + /* shouldn't throw +ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String; + */ + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/j+k/cantDeclareIfSamAdapterIsInherited.kt b/compiler/testData/diagnostics/tests/j+k/cantDeclareIfSamAdapterIsInherited.kt new file mode 100644 index 00000000000..ec64c6f6e04 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/cantDeclareIfSamAdapterIsInherited.kt @@ -0,0 +1,17 @@ +// FILE: Super.java +class Super { + void foo(Runnable r) { + } +} + +// FILE: Sub.kt +class Sub1() : Super() { + fun foo(r : (() -> Unit)?) { + } +} + +class Sub2() : Super() { + override fun foo(r : (() -> Unit)?) { + } +} + diff --git a/compiler/testData/diagnostics/tests/j+k/recursiveRawUpperBound.kt b/compiler/testData/diagnostics/tests/j+k/recursiveRawUpperBound.kt new file mode 100644 index 00000000000..afc8fc1e2eb --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/recursiveRawUpperBound.kt @@ -0,0 +1,13 @@ +// FILE: Bad.java + +class Bad {} + +// FILE: X.java + +class X { + Bad foo() {return null;} +} + +// FILE: Usage.kt + +fun foo(p: X) = p.foo() diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt b/compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt new file mode 100644 index 00000000000..b1504a71400 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt @@ -0,0 +1,25 @@ +//KT-3772 Invoke and overload resolution ambiguity +package bar + +open class A { + public fun invoke(f: A.() -> Unit) {} +} + +class B { + public fun invoke(f: B.() -> Unit) {} +} + +open class C +val C.attr = A() + +open class D: C() +val D.attr = B() + + +fun main(args: Array) { + val b = D() + b.attr {} // overload resolution ambiguity + + val d = b.attr + d {} // no error +} \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledJava/sam/SamSubinterfaceOfTwo.txt b/compiler/testData/loadJava/compiledJava/sam/SamSubinterfaceOfTwo.txt index 07f65c706d7..0d55aad0e86 100644 --- a/compiler/testData/loadJava/compiledJava/sam/SamSubinterfaceOfTwo.txt +++ b/compiler/testData/loadJava/compiledJava/sam/SamSubinterfaceOfTwo.txt @@ -3,7 +3,7 @@ package test public trait SamSubinterfaceOfTwo : java.lang.Object { public trait Sub : test.SamSubinterfaceOfTwo.Super1, test.SamSubinterfaceOfTwo.Super2 { - public abstract override /*2*/ /*fake_override*/ fun f(): jet.CharSequence? + public abstract override /*2*/ /*fake_override*/ fun f(): jet.String? } public trait Super1 : java.lang.Object { diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/AmbiguousAdapters.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/AmbiguousAdapters.txt index 8285524a2cb..56682f67e1f 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/AmbiguousAdapters.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/AmbiguousAdapters.txt @@ -2,8 +2,8 @@ package test public open class AmbiguousAdapters : java.lang.Object { public constructor AmbiguousAdapters() - public open /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit - public open /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public open fun foo(/*0*/ p0: java.io.Closeable?): jet.Unit public open fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/Basic.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/Basic.txt index fcc00409eae..a33203b260c 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/Basic.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/Basic.txt @@ -2,11 +2,11 @@ package test public open class Basic : java.lang.Object { public constructor Basic() - public open /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public open fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit } package Basic { - public open /*synthesized*/ fun bar(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public /*synthesized*/ fun bar(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public open fun bar(/*0*/ p0: java.lang.Runnable?): jet.Unit } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/DeepSamLoop.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/DeepSamLoop.txt index d558ccd28f4..8be90ed2977 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/DeepSamLoop.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/DeepSamLoop.txt @@ -3,12 +3,12 @@ package test public trait DeepSamLoop : java.lang.Object { public trait Bar : java.lang.Object { - public abstract /*synthesized*/ fun foo(/*0*/ p0: ((test.DeepSamLoop.Bar?) -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: ((test.DeepSamLoop.Bar?) -> jet.Unit)?): jet.Unit public abstract fun foo(/*0*/ p0: test.DeepSamLoop.Foo?): jet.Unit } public trait Foo : java.lang.Object { - public abstract /*synthesized*/ fun foo(/*0*/ p0: ((test.DeepSamLoop.Foo?) -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: ((test.DeepSamLoop.Foo?) -> jet.Unit)?): jet.Unit public abstract fun foo(/*0*/ p0: test.DeepSamLoop.Bar?): jet.Unit } } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/NonTrivialFunctionType.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/NonTrivialFunctionType.txt index ae0ee667381..d7c7ee885ec 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/NonTrivialFunctionType.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/NonTrivialFunctionType.txt @@ -2,11 +2,11 @@ package test public open class NonTrivialFunctionType : java.lang.Object { public constructor NonTrivialFunctionType() - public open /*synthesized*/ fun foo(/*0*/ p0: ((java.io.File, jet.String) -> jet.Boolean)?): jet.Unit - public open /*synthesized*/ fun foo(/*0*/ p0: ((jet.String, jet.String) -> jet.Int)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: ((java.io.File, jet.String) -> jet.Boolean)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: ((jet.String, jet.String) -> jet.Int)?): jet.Unit public open fun foo(/*0*/ p0: java.io.FilenameFilter?): jet.Unit public open fun foo(/*0*/ p0: java.util.Comparator?): jet.Unit - public open /*synthesized*/ fun wildcardBound(/*0*/ p0: ((jet.CharSequence?, jet.CharSequence?) -> jet.Int)?): jet.Unit + public final /*synthesized*/ fun wildcardBound(/*0*/ p0: ((jet.CharSequence?, jet.CharSequence?) -> jet.Int)?): jet.Unit public open fun wildcardBound(/*0*/ p0: java.util.Comparator?): jet.Unit public open fun wildcardUnbound(/*0*/ p0: java.util.Comparator?): jet.Unit } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/SelfAsParameter.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/SelfAsParameter.txt index d579c380a55..6be1be988f2 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/SelfAsParameter.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/SelfAsParameter.txt @@ -3,6 +3,6 @@ package test public /*synthesized*/ fun SelfAsParameter(/*0*/ function: (test.SelfAsParameter?) -> jet.Unit): test.SelfAsParameter public trait SelfAsParameter : java.lang.Object { - public abstract /*synthesized*/ fun foo(/*0*/ p0: ((test.SelfAsParameter?) -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: ((test.SelfAsParameter?) -> jet.Unit)?): jet.Unit public abstract fun foo(/*0*/ p0: test.SelfAsParameter?): jet.Unit } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/SeveralSamParameters.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/SeveralSamParameters.txt index 57b5508fe52..beb1fca6e31 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/SeveralSamParameters.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/SeveralSamParameters.txt @@ -5,6 +5,6 @@ public open class SeveralSamParameters : java.lang.Object { } package SeveralSamParameters { - public open /*synthesized*/ fun findMaxAndInvokeCallback(/*0*/ p0: ((jet.String, jet.String) -> jet.Int)?, /*1*/ p1: jet.String?, /*2*/ p2: jet.String?, /*3*/ p3: (() -> jet.Unit)?): jet.String? + public /*synthesized*/ fun findMaxAndInvokeCallback(/*0*/ p0: ((jet.String, jet.String) -> jet.Int)?, /*1*/ p1: jet.String?, /*2*/ p2: jet.String?, /*3*/ p3: (() -> jet.Unit)?): jet.String? public open fun findMaxAndInvokeCallback(/*0*/ p0: java.util.Comparator?, /*1*/ p1: jet.String?, /*2*/ p2: jet.String?, /*3*/ p3: java.lang.Runnable?): jet.String? } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfClass.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfClass.txt index aad57e1da24..a326e1a3193 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfClass.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfClass.txt @@ -2,6 +2,6 @@ package test public open class TypeParameterOfClass : java.lang.Object { public constructor TypeParameterOfClass() - public open /*synthesized*/ fun foo(/*0*/ p0: ((T, T) -> jet.Int)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: ((T, T) -> jet.Int)?): jet.Unit public open fun foo(/*0*/ p0: java.util.Comparator?): jet.Unit } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfMethod.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfMethod.txt index bacb260964b..bb75ea95373 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfMethod.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfMethod.txt @@ -5,10 +5,10 @@ public open class TypeParameterOfMethod : java.lang.Object { } package TypeParameterOfMethod { - public open /*synthesized*/ fun max(/*0*/ p0: ((T, T) -> jet.Int)?, /*1*/ p1: T?, /*2*/ p2: T?): T? + public /*synthesized*/ fun max(/*0*/ p0: ((T, T) -> jet.Int)?, /*1*/ p1: T?, /*2*/ p2: T?): T? public open fun max(/*0*/ p0: java.util.Comparator?, /*1*/ p1: T?, /*2*/ p2: T?): T? - public open /*synthesized*/ fun max2(/*0*/ p0: ((T, T) -> jet.Int)?, /*1*/ p1: T?, /*2*/ p2: T?): T? + public /*synthesized*/ fun max2(/*0*/ p0: ((T, T) -> jet.Int)?, /*1*/ p1: T?, /*2*/ p2: T?): T? public open fun max2(/*0*/ p0: java.util.Comparator?, /*1*/ p1: T?, /*2*/ p2: T?): T? - public open /*synthesized*/ fun ?> method(/*0*/ p0: ((A, A) -> jet.Int)?, /*1*/ p1: B?): jet.Unit + public /*synthesized*/ fun ?> method(/*0*/ p0: ((A, A) -> jet.Int)?, /*1*/ p1: B?): jet.Unit public open fun ?> method(/*0*/ p0: java.util.Comparator?, /*1*/ p1: B?): jet.Unit } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfOuterClass.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfOuterClass.txt index 1dbb3b17d9f..6310933b0c9 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfOuterClass.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfOuterClass.txt @@ -5,7 +5,7 @@ public open class TypeParameterOfOuterClass : java.lang.Object { public open inner class Inner : java.lang.Object { public constructor Inner() - public open /*synthesized*/ fun foo(/*0*/ p0: ((T, T) -> jet.Int)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: ((T, T) -> jet.Int)?): jet.Unit public open fun foo(/*0*/ p0: java.util.Comparator?): jet.Unit } } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/AdapterDoesntOverrideDeclaration.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/AdapterDoesntOverrideDeclaration.java new file mode 100644 index 00000000000..ae3f6895344 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/AdapterDoesntOverrideDeclaration.java @@ -0,0 +1,11 @@ +package test; + +public interface AdapterDoesntOverrideDeclaration { + public interface Super { + void foo(jet.Function0 r); + } + + public interface Sub extends Super { + void foo(Runnable r); + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/AdapterDoesntOverrideDeclaration.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/AdapterDoesntOverrideDeclaration.txt new file mode 100644 index 00000000000..61dd4f803ba --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/AdapterDoesntOverrideDeclaration.txt @@ -0,0 +1,18 @@ +package test + +public trait AdapterDoesntOverrideDeclaration : java.lang.Object { + + public trait Sub : test.AdapterDoesntOverrideDeclaration.Super { + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } + + public trait Super : java.lang.Object { + public abstract fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + } +} + +package AdapterDoesntOverrideDeclaration { + public /*synthesized*/ fun Super(/*0*/ function: ((() -> jet.Unit)?) -> jet.Unit): test.AdapterDoesntOverrideDeclaration.Super +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAdapterAndDeclaration.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAdapterAndDeclaration.java new file mode 100644 index 00000000000..26cb97e0900 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAdapterAndDeclaration.java @@ -0,0 +1,11 @@ +package test; + +public interface InheritedAdapterAndDeclaration { + public interface Super { + void foo(Runnable r); + void foo(jet.Function0 r); + } + + public interface Sub extends Super { + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAdapterAndDeclaration.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAdapterAndDeclaration.txt new file mode 100644 index 00000000000..d4614d59b8d --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAdapterAndDeclaration.txt @@ -0,0 +1,16 @@ +package test + +public trait InheritedAdapterAndDeclaration : java.lang.Object { + + public trait Sub : test.InheritedAdapterAndDeclaration.Super { + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } + + public trait Super : java.lang.Object { + public abstract fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAmbiguousAdapters.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAmbiguousAdapters.java new file mode 100644 index 00000000000..48cca68f6a6 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAmbiguousAdapters.java @@ -0,0 +1,13 @@ +package test; + +import java.io.Closeable; + +public interface InheritedAmbiguousAdapters { + public interface Super { + void foo(Runnable r); + void foo(Closeable r); + } + + public interface Sub extends Super { + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAmbiguousAdapters.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAmbiguousAdapters.txt new file mode 100644 index 00000000000..66a1df2f265 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAmbiguousAdapters.txt @@ -0,0 +1,18 @@ +package test + +public trait InheritedAmbiguousAdapters : java.lang.Object { + + public trait Sub : test.InheritedAmbiguousAdapters.Super { + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.io.Closeable?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } + + public trait Super : java.lang.Object { + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.io.Closeable?): jet.Unit + public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAndOverriddenAmbiguousAdapters.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAndOverriddenAmbiguousAdapters.java new file mode 100644 index 00000000000..39f7f7efa46 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAndOverriddenAmbiguousAdapters.java @@ -0,0 +1,14 @@ +package test; + +import java.io.Closeable; + +public interface InheritedAndOverriddenAmbiguousAdapters { + public interface Super { + void foo(Runnable r); + void foo(Closeable r); + } + + public interface Sub extends Super { + void foo(Runnable r); + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAndOverriddenAmbiguousAdapters.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAndOverriddenAmbiguousAdapters.txt new file mode 100644 index 00000000000..396c1dc3f3b --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAndOverriddenAmbiguousAdapters.txt @@ -0,0 +1,18 @@ +package test + +public trait InheritedAndOverriddenAmbiguousAdapters : java.lang.Object { + + public trait Sub : test.InheritedAndOverriddenAmbiguousAdapters.Super { + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final override /*1*/ /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.io.Closeable?): jet.Unit + public abstract override /*1*/ fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } + + public trait Super : java.lang.Object { + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.io.Closeable?): jet.Unit + public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverridden.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverridden.java similarity index 100% rename from compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverridden.java rename to compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverridden.java diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverridden.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverridden.txt similarity index 69% rename from compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverridden.txt rename to compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverridden.txt index 5a55c36f4b1..4bdb829be47 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverridden.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverridden.txt @@ -4,13 +4,13 @@ public trait InheritedOverridden : java.lang.Object { public open class Sub : test.InheritedOverridden.Super { public constructor Sub() - public open override /*1*/ /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final override /*1*/ /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public open override /*1*/ fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit } public open class Super : java.lang.Object { public constructor Super() - public open /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public open fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit } } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverriddenAdapter.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverriddenAdapter.java similarity index 100% rename from compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverriddenAdapter.java rename to compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverriddenAdapter.java diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverriddenAdapter.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverriddenAdapter.txt similarity index 86% rename from compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverriddenAdapter.txt rename to compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverriddenAdapter.txt index a504c87944d..fc0ae4d9ffe 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverriddenAdapter.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverriddenAdapter.txt @@ -10,7 +10,7 @@ public trait InheritedOverriddenAdapter : java.lang.Object { public open class Super : java.lang.Object { public constructor Super() - public open /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public open fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit } } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdapters.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdapters.java new file mode 100644 index 00000000000..1d0e88e2009 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdapters.java @@ -0,0 +1,14 @@ +package test; + +public interface InheritedSameAdapters { + public interface Super1 { + void foo(Runnable r); + } + + public interface Super2 { + void foo(Runnable r); + } + + public interface Sub extends Super1, Super2 { + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdapters.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdapters.txt new file mode 100644 index 00000000000..a9416c0c8ac --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdapters.txt @@ -0,0 +1,25 @@ +package test + +public trait InheritedSameAdapters : java.lang.Object { + + public trait Sub : test.InheritedSameAdapters.Super1, test.InheritedSameAdapters.Super2 { + public final override /*2*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } + + public trait Super1 : java.lang.Object { + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } + + public trait Super2 : java.lang.Object { + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } +} + +package InheritedSameAdapters { + public /*synthesized*/ fun Sub(/*0*/ function: (java.lang.Runnable?) -> jet.Unit): test.InheritedSameAdapters.Sub + public /*synthesized*/ fun Super1(/*0*/ function: (java.lang.Runnable?) -> jet.Unit): test.InheritedSameAdapters.Super1 + public /*synthesized*/ fun Super2(/*0*/ function: (java.lang.Runnable?) -> jet.Unit): test.InheritedSameAdapters.Super2 +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdaptersWithSubstitution.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdaptersWithSubstitution.java new file mode 100644 index 00000000000..061c3b40ac4 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdaptersWithSubstitution.java @@ -0,0 +1,19 @@ +package test; + +import java.util.Comparator; + +public interface InheritedSameAdaptersWithSubstitution { + public interface Super1 { + void foo(Comparator r); + } + + public interface Super2 { + void foo(Comparator r); + } + + public interface Super2Substituted extends Super2 { + } + + public interface Sub extends Super1, Super2Substituted { + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdaptersWithSubstitution.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdaptersWithSubstitution.txt new file mode 100644 index 00000000000..34ede216604 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdaptersWithSubstitution.txt @@ -0,0 +1,31 @@ +package test + +public trait InheritedSameAdaptersWithSubstitution : java.lang.Object { + + public trait Sub : test.InheritedSameAdaptersWithSubstitution.Super1, test.InheritedSameAdaptersWithSubstitution.Super2Substituted { + public final override /*2*/ /*fake_override*/ fun foo(/*0*/ p0: ((jet.String, jet.String) -> jet.Int)?): jet.Unit + public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ p0: java.util.Comparator?): jet.Unit + } + + public trait Super1 : java.lang.Object { + public final /*synthesized*/ fun foo(/*0*/ p0: ((jet.String, jet.String) -> jet.Int)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.util.Comparator?): jet.Unit + } + + public trait Super2 : java.lang.Object { + public final /*synthesized*/ fun foo(/*0*/ p0: ((T, T) -> jet.Int)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.util.Comparator?): jet.Unit + } + + public trait Super2Substituted : test.InheritedSameAdaptersWithSubstitution.Super2 { + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: ((jet.String, jet.String) -> jet.Int)?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.util.Comparator?): jet.Unit + } +} + +package InheritedSameAdaptersWithSubstitution { + public /*synthesized*/ fun Sub(/*0*/ function: (java.util.Comparator?) -> jet.Unit): test.InheritedSameAdaptersWithSubstitution.Sub + public /*synthesized*/ fun Super1(/*0*/ function: (java.util.Comparator?) -> jet.Unit): test.InheritedSameAdaptersWithSubstitution.Super1 + public /*synthesized*/ fun Super2(/*0*/ function: (java.util.Comparator?) -> jet.Unit): test.InheritedSameAdaptersWithSubstitution.Super2 + public /*synthesized*/ fun Super2Substituted(/*0*/ function: (java.util.Comparator?) -> jet.Unit): test.InheritedSameAdaptersWithSubstitution.Super2Substituted +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedSimple.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSimple.java similarity index 98% rename from compiler/testData/loadJava/compiledJava/sam/adapters/InheritedSimple.java rename to compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSimple.java index 66c7a3c1988..47dfb45759e 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedSimple.java +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSimple.java @@ -7,4 +7,4 @@ public interface InheritedSimple { public interface Sub extends Super { } -} \ No newline at end of file +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedSimple.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSimple.txt similarity index 76% rename from compiler/testData/loadJava/compiledJava/sam/adapters/InheritedSimple.txt rename to compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSimple.txt index 10534b8b49e..53ab0dfb4d4 100644 --- a/compiler/testData/loadJava/compiledJava/sam/adapters/InheritedSimple.txt +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSimple.txt @@ -3,12 +3,12 @@ package test public trait InheritedSimple : java.lang.Object { public trait Sub : test.InheritedSimple.Super { - public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit } public trait Super : java.lang.Object { - public abstract /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit } } diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/OverriddenAmbiguousAdapters.java b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/OverriddenAmbiguousAdapters.java new file mode 100644 index 00000000000..08409d2c53d --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/OverriddenAmbiguousAdapters.java @@ -0,0 +1,14 @@ +package test; + +import java.io.Closeable; + +public interface OverriddenAmbiguousAdapters { + public interface Super { + void foo(Runnable r); + void foo(Closeable r); + } + + public interface Sub extends Super { + void foo(jet.Function0 r); + } +} diff --git a/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/OverriddenAmbiguousAdapters.txt b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/OverriddenAmbiguousAdapters.txt new file mode 100644 index 00000000000..1796c58440b --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/OverriddenAmbiguousAdapters.txt @@ -0,0 +1,17 @@ +package test + +public trait OverriddenAmbiguousAdapters : java.lang.Object { + + public trait Sub : test.OverriddenAmbiguousAdapters.Super { + public abstract override /*2*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.io.Closeable?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } + + public trait Super : java.lang.Object { + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ p0: (() -> jet.Unit)?): jet.Unit + public abstract fun foo(/*0*/ p0: java.io.Closeable?): jet.Unit + public abstract fun foo(/*0*/ p0: java.lang.Runnable?): jet.Unit + } +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.java b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.java new file mode 100644 index 00000000000..0282290e82b --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.java @@ -0,0 +1,16 @@ +package test; + +public final class InheritMethodsDifferentReturnTypes { + public interface Super1 { + CharSequence foo(); + String bar(); + } + + public interface Super2 { + String foo(); + CharSequence bar(); + } + + public interface Sub extends Super1, Super2 { + } +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.kt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.kt new file mode 100644 index 00000000000..e291a385068 --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.kt @@ -0,0 +1,16 @@ +package test + +public class InheritMethodsDifferentReturnTypes: Object() { + public trait Super1: Object { + public fun foo(): CharSequence? + public fun bar(): String? + } + + public trait Super2: Object { + public fun foo(): String? + public fun bar(): CharSequence? + } + + public trait Sub: Super1, Super2 { + } +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.txt new file mode 100644 index 00000000000..a885a84160d --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.txt @@ -0,0 +1,20 @@ +package test + +public final class InheritMethodsDifferentReturnTypes : java.lang.Object { + public constructor InheritMethodsDifferentReturnTypes() + + public trait Sub : test.InheritMethodsDifferentReturnTypes.Super1, test.InheritMethodsDifferentReturnTypes.Super2 { + public abstract override /*2*/ /*fake_override*/ fun bar(): jet.String? + public abstract override /*2*/ /*fake_override*/ fun foo(): jet.String? + } + + public trait Super1 : java.lang.Object { + public abstract fun bar(): jet.String? + public abstract fun foo(): jet.CharSequence? + } + + public trait Super2 : java.lang.Object { + public abstract fun bar(): jet.CharSequence? + public abstract fun foo(): jet.String? + } +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.java b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.java new file mode 100644 index 00000000000..8f302a9ee9e --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.java @@ -0,0 +1,16 @@ +package test; + +public final class InheritMethodsDifferentReturnTypesGeneric { + public interface Super1 { + F foo(); + B bar(); + } + + public interface Super2 { + FF foo(); + BB bar(); + } + + public interface Sub extends Super1, Super2 { + } +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.kt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.kt new file mode 100644 index 00000000000..4d5f479f891 --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.kt @@ -0,0 +1,16 @@ +package test + +public class InheritMethodsDifferentReturnTypesGeneric: Object() { + public trait Super1: Object { + public fun foo(): F? + public fun bar(): B? + } + + public trait Super2: Object { + public fun foo(): FF? + public fun bar(): BB? + } + + public trait Sub: Super1, Super2 { + } +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.txt new file mode 100644 index 00000000000..d4bb464002c --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.txt @@ -0,0 +1,20 @@ +package test + +public final class InheritMethodsDifferentReturnTypesGeneric : java.lang.Object { + public constructor InheritMethodsDifferentReturnTypesGeneric() + + public trait Sub : test.InheritMethodsDifferentReturnTypesGeneric.Super1, test.InheritMethodsDifferentReturnTypesGeneric.Super2 { + public abstract override /*2*/ /*fake_override*/ fun bar(): jet.String? + public abstract override /*2*/ /*fake_override*/ fun foo(): jet.String? + } + + public trait Super1 : java.lang.Object { + public abstract fun bar(): B? + public abstract fun foo(): F? + } + + public trait Super2 : java.lang.Object { + public abstract fun bar(): BB? + public abstract fun foo(): FF? + } +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/return/HalfSubstitutedTypeParameters.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/return/HalfSubstitutedTypeParameters.txt index b94568c8ca3..8a4cc197422 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/return/HalfSubstitutedTypeParameters.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/return/HalfSubstitutedTypeParameters.txt @@ -23,7 +23,7 @@ public trait HalfSubstitutedTypeParameters : java.lang.Object { public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ index: jet.Int): E public abstract override /*1*/ /*fake_override*/ fun indexOf(/*0*/ o: jet.Any?): jet.Int public abstract override /*1*/ /*fake_override*/ fun isEmpty(): jet.Boolean - public abstract override /*1*/ /*fake_override*/ fun iterator(): jet.Iterator + public abstract override /*1*/ /*fake_override*/ fun iterator(): jet.MutableIterator public abstract override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: jet.Any?): jet.Int public abstract override /*1*/ /*fake_override*/ fun listIterator(): jet.MutableListIterator public abstract override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: jet.Int): jet.MutableListIterator diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/modality/ModalityOfFakeOverrides.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/modality/ModalityOfFakeOverrides.txt index 01ae4e35e02..624c700c37f 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/modality/ModalityOfFakeOverrides.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/modality/ModalityOfFakeOverrides.txt @@ -5,11 +5,11 @@ public open class ModalityOfFakeOverrides : java.util.AbstractList { protected final override /*1*/ /*fake_override*/ var modCount: jet.Int public open override /*1*/ /*fake_override*/ fun add(/*0*/ p0: jet.Int, /*1*/ p1: jet.String): jet.Unit public open override /*1*/ /*fake_override*/ fun add(/*0*/ p0: jet.String): jet.Boolean - public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ p0: jet.Collection): jet.Boolean + public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ c: jet.Collection): jet.Boolean public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ p0: jet.Int, /*1*/ p1: jet.Collection): jet.Boolean public open override /*1*/ /*fake_override*/ fun clear(): jet.Unit - public open override /*1*/ /*fake_override*/ fun contains(/*0*/ p0: jet.Any?): jet.Boolean - public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ p0: jet.Collection): jet.Boolean + public open override /*1*/ /*fake_override*/ fun contains(/*0*/ o: jet.Any?): jet.Boolean + public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ c: jet.Collection): jet.Boolean public open override /*1*/ fun get(/*0*/ p0: jet.Int): jet.String public open override /*1*/ /*fake_override*/ fun indexOf(/*0*/ p0: jet.Any?): jet.Int public open override /*1*/ /*fake_override*/ fun isEmpty(): jet.Boolean @@ -17,11 +17,11 @@ public open class ModalityOfFakeOverrides : java.util.AbstractList { public open override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ p0: jet.Any?): jet.Int public open override /*1*/ /*fake_override*/ fun listIterator(): jet.MutableListIterator public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ p0: jet.Int): jet.MutableListIterator - public open override /*1*/ /*fake_override*/ fun remove(/*0*/ p0: jet.Any?): jet.Boolean + public open override /*1*/ /*fake_override*/ fun remove(/*0*/ o: jet.Any?): jet.Boolean public open override /*1*/ /*fake_override*/ fun remove(/*0*/ p0: jet.Int): jet.String - public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ p0: jet.Collection): jet.Boolean + public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ c: jet.Collection): jet.Boolean protected open override /*1*/ /*fake_override*/ fun removeRange(/*0*/ p0: jet.Int, /*1*/ p1: jet.Int): jet.Unit - public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ p0: jet.Collection): jet.Boolean + public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ c: jet.Collection): jet.Boolean public open override /*1*/ /*fake_override*/ fun set(/*0*/ p0: jet.Int, /*1*/ p1: jet.String): jet.String public open override /*1*/ fun size(): jet.Int public open override /*1*/ /*fake_override*/ fun subList(/*0*/ p0: jet.Int, /*1*/ p1: jet.Int): jet.MutableList diff --git a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin.txt b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin.txt new file mode 100644 index 00000000000..d3edaac6e68 --- /dev/null +++ b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin.txt @@ -0,0 +1,17 @@ +package test + +public final class Sub : test.Super { + public constructor Sub() + internal final override /*1*/ /*fake_override*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit + internal final override /*1*/ /*fake_override*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit + internal open override /*1*/ /*fake_override*/ fun foo(/*0*/ r: java.io.Closeable?): jet.Unit + internal open override /*1*/ /*fake_override*/ fun foo(/*0*/ r: java.lang.Runnable?): jet.Unit +} + +public open class Super : java.lang.Object { + public constructor Super() + public/*package*/ final /*synthesized*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit + public/*package*/ final /*synthesized*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit + public/*package*/ open fun foo(/*0*/ r: java.io.Closeable?): jet.Unit + public/*package*/ open fun foo(/*0*/ r: java.lang.Runnable?): jet.Unit +} diff --git a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin/Sub.kt b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin/Sub.kt new file mode 100644 index 00000000000..697db35654f --- /dev/null +++ b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin/Sub.kt @@ -0,0 +1,4 @@ +package test + +public class Sub: Super() { +} diff --git a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin/Super.java b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin/Super.java new file mode 100644 index 00000000000..fd4102991bd --- /dev/null +++ b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin/Super.java @@ -0,0 +1,8 @@ +package test; + +import java.io.Closeable; + +public class Super { + void foo(Runnable r); + void foo(Closeable r); +} diff --git a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritSamAdapterInKotlin.txt b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritSamAdapterInKotlin.txt index 37250d7e3fb..6be8b56bd1c 100644 --- a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritSamAdapterInKotlin.txt +++ b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritSamAdapterInKotlin.txt @@ -2,12 +2,12 @@ package test public final class Sub : test.Super { public constructor Sub() - internal open override /*1*/ /*fake_override*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit + internal final override /*1*/ /*fake_override*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit internal open override /*1*/ /*fake_override*/ fun foo(/*0*/ r: java.lang.Runnable?): jet.Unit } public open class Super : java.lang.Object { public constructor Super() - public/*package*/ open /*synthesized*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit + public/*package*/ final /*synthesized*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit public/*package*/ open fun foo(/*0*/ r: java.lang.Runnable?): jet.Unit } diff --git a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/OverrideSamAdapterInKotlin.txt b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/OverrideSamAdapterInKotlin.txt index cf8b53614d4..9cbea61baee 100644 --- a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/OverrideSamAdapterInKotlin.txt +++ b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/OverrideSamAdapterInKotlin.txt @@ -8,6 +8,6 @@ public final class Sub : test.Super { public open class Super : java.lang.Object { public constructor Super() - public/*package*/ open /*synthesized*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit + public/*package*/ final /*synthesized*/ fun foo(/*0*/ r: (() -> jet.Unit)?): jet.Unit public/*package*/ open fun foo(/*0*/ r: java.lang.Runnable?): jet.Unit } diff --git a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/SamAdapterForOverriddenFromKotlin.txt b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/SamAdapterForOverriddenFromKotlin.txt index 18869710ad3..7ffeefde529 100644 --- a/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/SamAdapterForOverriddenFromKotlin.txt +++ b/compiler/testData/loadJava/javaAgainstKotlin/samAdapters/SamAdapterForOverriddenFromKotlin.txt @@ -2,7 +2,7 @@ package test public open class Sub : test.Super { public constructor Sub() - public open /*synthesized*/ fun foo(/*0*/ r: () -> jet.Unit): jet.Unit + public final /*synthesized*/ fun foo(/*0*/ r: () -> jet.Unit): jet.Unit public open override /*1*/ fun foo(/*0*/ r: java.lang.Runnable): jet.Unit } diff --git a/compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt b/compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt new file mode 100644 index 00000000000..22f48cf32c6 --- /dev/null +++ b/compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt @@ -0,0 +1,14 @@ +package test + +public trait Super1 { + public fun foo(): CharSequence + private fun bar(): String +} + +public trait Super2 { + private fun foo(): String + public fun bar(): CharSequence +} + +public trait Sub: Super1, Super2 { +} diff --git a/compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.txt b/compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.txt new file mode 100644 index 00000000000..d5ce427d1c6 --- /dev/null +++ b/compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.txt @@ -0,0 +1,16 @@ +package test + +public trait Sub : test.Super1, test.Super2 { + public abstract override /*1*/ /*fake_override*/ fun bar(): jet.CharSequence + public abstract override /*1*/ /*fake_override*/ fun foo(): jet.CharSequence +} + +public trait Super1 { + private abstract fun bar(): jet.String + public abstract fun foo(): jet.CharSequence +} + +public trait Super2 { + public abstract fun bar(): jet.CharSequence + private abstract fun foo(): jet.String +} diff --git a/compiler/testData/loadKotlin/fun/InheritValAndVar.kt b/compiler/testData/loadKotlin/fun/InheritValAndVar.kt new file mode 100644 index 00000000000..da7b91104bb --- /dev/null +++ b/compiler/testData/loadKotlin/fun/InheritValAndVar.kt @@ -0,0 +1,14 @@ +package test + +public trait Super1 { + val x: String + var y: String +} + +public trait Super2 { + var x: String + val y: String +} + +public trait Sub: Super1, Super2 { +} diff --git a/compiler/testData/loadKotlin/fun/InheritValAndVar.txt b/compiler/testData/loadKotlin/fun/InheritValAndVar.txt new file mode 100644 index 00000000000..917b4b8cd2e --- /dev/null +++ b/compiler/testData/loadKotlin/fun/InheritValAndVar.txt @@ -0,0 +1,26 @@ +package test + +public trait Sub : test.Super1, test.Super2 { + internal abstract override /*2*/ /*fake_override*/ var x: jet.String + internal abstract override /*2*/ /*fake_override*/ fun (): jet.String + internal abstract override /*1*/ /*fake_override*/ fun (/*0*/ : jet.String): jet.Unit + internal abstract override /*2*/ /*fake_override*/ var y: jet.String + internal abstract override /*2*/ /*fake_override*/ fun (): jet.String + internal abstract override /*1*/ /*fake_override*/ fun (/*0*/ : jet.String): jet.Unit +} + +public trait Super1 { + internal abstract val x: jet.String + internal abstract fun (): jet.String + internal abstract var y: jet.String + internal abstract fun (): jet.String + internal abstract fun (/*0*/ : jet.String): jet.Unit +} + +public trait Super2 { + internal abstract var x: jet.String + internal abstract fun (): jet.String + internal abstract fun (/*0*/ : jet.String): jet.Unit + internal abstract val y: jet.String + internal abstract fun (): jet.String +} diff --git a/compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.kt b/compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.kt new file mode 100644 index 00000000000..63759c05d2e --- /dev/null +++ b/compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.kt @@ -0,0 +1,14 @@ +package test + +public trait Super1 { + val x: String + val y: CharSequence +} + +public trait Super2 { + val x: CharSequence + val y: String +} + +public trait Sub: Super1, Super2 { +} diff --git a/compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.txt b/compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.txt new file mode 100644 index 00000000000..40caba49eba --- /dev/null +++ b/compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.txt @@ -0,0 +1,22 @@ +package test + +public trait Sub : test.Super1, test.Super2 { + internal abstract override /*2*/ /*fake_override*/ val x: jet.String + internal abstract override /*2*/ /*fake_override*/ fun (): jet.String + internal abstract override /*2*/ /*fake_override*/ val y: jet.String + internal abstract override /*2*/ /*fake_override*/ fun (): jet.String +} + +public trait Super1 { + internal abstract val x: jet.String + internal abstract fun (): jet.String + internal abstract val y: jet.CharSequence + internal abstract fun (): jet.CharSequence +} + +public trait Super2 { + internal abstract val x: jet.CharSequence + internal abstract fun (): jet.CharSequence + internal abstract val y: jet.String + internal abstract fun (): jet.String +} diff --git a/compiler/testData/psi/NewLinesValidOperations.jet b/compiler/testData/psi/NewLinesValidOperations.jet index 1a9483d7f62..7d4c30511cc 100644 --- a/compiler/testData/psi/NewLinesValidOperations.jet +++ b/compiler/testData/psi/NewLinesValidOperations.jet @@ -8,4 +8,29 @@ fun test() { str ?.length + + str + + : String + + str + + as String + + str + + as? String + + str + + ?: foo + + true + + || false + + + false + + && true } \ No newline at end of file diff --git a/compiler/testData/psi/NewLinesValidOperations.txt b/compiler/testData/psi/NewLinesValidOperations.txt index a340c1270ef..8c64b13a7e0 100644 --- a/compiler/testData/psi/NewLinesValidOperations.txt +++ b/compiler/testData/psi/NewLinesValidOperations.txt @@ -38,5 +38,71 @@ JetFile: NewLinesValidOperations.jet PsiElement(SAFE_ACCESS)('?.') REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('length') + PsiWhiteSpace('\n\n ') + BINARY_WITH_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('str') + PsiWhiteSpace('\n\n ') + OPERATION_REFERENCE + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('String') + PsiWhiteSpace('\n\n ') + BINARY_WITH_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('str') + PsiWhiteSpace('\n\n ') + OPERATION_REFERENCE + PsiElement(as)('as') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('String') + PsiWhiteSpace('\n\n ') + BINARY_WITH_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('str') + PsiWhiteSpace('\n\n ') + OPERATION_REFERENCE + PsiElement(AS_SAFE)('as?') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('String') + PsiWhiteSpace('\n\n ') + BINARY_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('str') + PsiWhiteSpace('\n\n ') + OPERATION_REFERENCE + PsiElement(ELVIS)('?:') + PsiWhiteSpace(' ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace('\n\n ') + BINARY_EXPRESSION + BOOLEAN_CONSTANT + PsiElement(true)('true') ª + PsiWhiteSpace('\n\n ') + OPERATION_REFERENCE + PsiElement(OROR)('||') + PsiWhiteSpace(' ') + BOOLEAN_CONSTANT + PsiElement(false)('false') + PsiWhiteSpace('\n\n\n ') + BINARY_EXPRESSION + BOOLEAN_CONSTANT + PsiElement(false)('false') + PsiWhiteSpace('\n\n ') + OPERATION_REFERENCE + PsiElement(ANDAND)('&&') + PsiWhiteSpace(' ') + BOOLEAN_CONSTANT + PsiElement(true)('true') PsiWhiteSpace('\n') PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/writeSignature/ArrayOfInt.kt b/compiler/testData/writeSignature/ArrayOfInt.kt index cba50792681..6401af29b7b 100644 --- a/compiler/testData/writeSignature/ArrayOfInt.kt +++ b/compiler/testData/writeSignature/ArrayOfInt.kt @@ -3,4 +3,4 @@ fun never(): Array = throw Exception() // method: _DefaultPackage::never // jvm signature: ()[Ljava/lang/Integer; // generic signature: null -// kotlin signature: ()[Ljava/lang/Integer; // TODO: need to skip kotlin signature +// kotlin signature: ()[Ljet/Int; // TODO: need to skip kotlin signature diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index abb5951ef74..530f0bbe8a7 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -3234,6 +3234,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/j+k/ambiguousSamAdapters.kt"); } + @TestMetadata("cantDeclareIfSamAdapterIsInherited.kt") + public void testCantDeclareIfSamAdapterIsInherited() throws Exception { + doTest("compiler/testData/diagnostics/tests/j+k/cantDeclareIfSamAdapterIsInherited.kt"); + } + @TestMetadata("inheritAbstractSamAdapter.kt") public void testInheritAbstractSamAdapter() throws Exception { doTest("compiler/testData/diagnostics/tests/j+k/inheritAbstractSamAdapter.kt"); @@ -3314,6 +3319,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/j+k/packageVisibility.kt"); } + @TestMetadata("recursiveRawUpperBound.kt") + public void testRecursiveRawUpperBound() throws Exception { + doTest("compiler/testData/diagnostics/tests/j+k/recursiveRawUpperBound.kt"); + } + @TestMetadata("Simple.kt") public void testSimple() throws Exception { doTest("compiler/testData/diagnostics/tests/j+k/Simple.kt"); @@ -4572,6 +4582,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/resolve/invoke/invokeAsMemberExtensionToExplicitReceiver.kt"); } + @TestMetadata("kt3772.kt") + public void testKt3772() throws Exception { + doTest("compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt"); + } + } public static Test innerSuite() { diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index d51be1ac644..86502eaff94 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -178,11 +178,6 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege doTestWithJava("compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapter.kt"); } - @TestMetadata("inheritedOverriddenAdapterInKotlin.kt") - public void testInheritedOverriddenAdapterInKotlin() throws Exception { - doTestWithJava("compiler/testData/codegen/boxWithJava/sam/adapters/inheritedOverriddenAdapterInKotlin.kt"); - } - @TestMetadata("inheritedSimple.kt") public void testInheritedSimple() throws Exception { doTestWithJava("compiler/testData/codegen/boxWithJava/sam/adapters/inheritedSimple.kt"); diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 24e69e94441..5d2e99c1665 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/boxWithStdlib") -@InnerTestClasses({BlackBoxWithStdlibCodegenTestGenerated.Annotations.class, BlackBoxWithStdlibCodegenTestGenerated.Casts.class, BlackBoxWithStdlibCodegenTestGenerated.DataClasses.class, BlackBoxWithStdlibCodegenTestGenerated.FullJdk.class, BlackBoxWithStdlibCodegenTestGenerated.JdkAnnotations.class, BlackBoxWithStdlibCodegenTestGenerated.Ranges.class, BlackBoxWithStdlibCodegenTestGenerated.Regressions.class, BlackBoxWithStdlibCodegenTestGenerated.Strings.class}) +@InnerTestClasses({BlackBoxWithStdlibCodegenTestGenerated.Annotations.class, BlackBoxWithStdlibCodegenTestGenerated.Arrays.class, BlackBoxWithStdlibCodegenTestGenerated.Casts.class, BlackBoxWithStdlibCodegenTestGenerated.DataClasses.class, BlackBoxWithStdlibCodegenTestGenerated.FullJdk.class, BlackBoxWithStdlibCodegenTestGenerated.JdkAnnotations.class, BlackBoxWithStdlibCodegenTestGenerated.Ranges.class, BlackBoxWithStdlibCodegenTestGenerated.Regressions.class, BlackBoxWithStdlibCodegenTestGenerated.Strings.class}) public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInBoxWithStdlib() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithStdlib"), Pattern.compile("^(.+)\\.kt$"), true); @@ -50,6 +50,19 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode } + @TestMetadata("compiler/testData/codegen/boxWithStdlib/arrays") + public static class Arrays extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInArrays() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithStdlib/arrays"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("kt3771.kt") + public void testKt3771() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/arrays/kt3771.kt"); + } + + } + @TestMetadata("compiler/testData/codegen/boxWithStdlib/casts") public static class Casts extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInCasts() throws Exception { @@ -896,6 +909,7 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode TestSuite suite = new TestSuite("BlackBoxWithStdlibCodegenTestGenerated"); suite.addTestSuite(BlackBoxWithStdlibCodegenTestGenerated.class); suite.addTestSuite(Annotations.class); + suite.addTestSuite(Arrays.class); suite.addTestSuite(Casts.class); suite.addTest(DataClasses.innerSuite()); suite.addTestSuite(FullJdk.class); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index 5a3b33e8e68..4416d106319 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -444,6 +444,21 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/fun"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("InheritMethodsDifferentReturnTypesAndVisibilities.kt") + public void testInheritMethodsDifferentReturnTypesAndVisibilities() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt"); + } + + @TestMetadata("InheritValAndVar.kt") + public void testInheritValAndVar() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/fun/InheritValAndVar.kt"); + } + + @TestMetadata("InheritValsDifferentTypes.kt") + public void testInheritValsDifferentTypes() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.kt"); + } + @TestMetadata("NoSamAdapter.kt") public void testNoSamAdapter() throws Exception { doTestWithAccessors("compiler/testData/loadKotlin/fun/NoSamAdapter.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 1a3b36ce16c..a67c4de380f 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -94,6 +94,16 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTest("compiler/testData/loadJava/compiledJavaCompareWithKotlin/FinalFieldAsVal.java"); } + @TestMetadata("InheritMethodsDifferentReturnTypes.java") + public void testInheritMethodsDifferentReturnTypes() throws Exception { + doTest("compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.java"); + } + + @TestMetadata("InheritMethodsDifferentReturnTypesGeneric.java") + public void testInheritMethodsDifferentReturnTypesGeneric() throws Exception { + doTest("compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.java"); + } + @TestMetadata("InnerClass.java") public void testInnerClass() throws Exception { doTest("compiler/testData/loadJava/compiledJavaCompareWithKotlin/InnerClass.java"); @@ -1201,6 +1211,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { } @TestMetadata("compiler/testData/loadJava/compiledJava/sam/adapters") + @InnerTestClasses({Adapters.Inheritance.class}) public static class Adapters extends AbstractLoadJavaTest { public void testAllFilesPresentInAdapters() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/sam/adapters"), Pattern.compile("^(.+)\\.java$"), true); @@ -1226,21 +1237,6 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/DeepSamLoop.java"); } - @TestMetadata("InheritedOverridden.java") - public void testInheritedOverridden() throws Exception { - doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverridden.java"); - } - - @TestMetadata("InheritedOverriddenAdapter.java") - public void testInheritedOverriddenAdapter() throws Exception { - doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/InheritedOverriddenAdapter.java"); - } - - @TestMetadata("InheritedSimple.java") - public void testInheritedSimple() throws Exception { - doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/InheritedSimple.java"); - } - @TestMetadata("NonTrivialFunctionType.java") public void testNonTrivialFunctionType() throws Exception { doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/NonTrivialFunctionType.java"); @@ -1271,12 +1267,76 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/TypeParameterOfOuterClass.java"); } + @TestMetadata("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance") + public static class Inheritance extends AbstractLoadJavaTest { + @TestMetadata("AdapterDoesntOverrideDeclaration.java") + public void testAdapterDoesntOverrideDeclaration() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/AdapterDoesntOverrideDeclaration.java"); + } + + public void testAllFilesPresentInInheritance() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("InheritedAdapterAndDeclaration.java") + public void testInheritedAdapterAndDeclaration() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAdapterAndDeclaration.java"); + } + + @TestMetadata("InheritedAmbiguousAdapters.java") + public void testInheritedAmbiguousAdapters() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAmbiguousAdapters.java"); + } + + @TestMetadata("InheritedAndOverriddenAmbiguousAdapters.java") + public void testInheritedAndOverriddenAmbiguousAdapters() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedAndOverriddenAmbiguousAdapters.java"); + } + + @TestMetadata("InheritedOverridden.java") + public void testInheritedOverridden() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverridden.java"); + } + + @TestMetadata("InheritedOverriddenAdapter.java") + public void testInheritedOverriddenAdapter() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedOverriddenAdapter.java"); + } + + @TestMetadata("InheritedSameAdapters.java") + public void testInheritedSameAdapters() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdapters.java"); + } + + @TestMetadata("InheritedSameAdaptersWithSubstitution.java") + public void testInheritedSameAdaptersWithSubstitution() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSameAdaptersWithSubstitution.java"); + } + + @TestMetadata("InheritedSimple.java") + public void testInheritedSimple() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/InheritedSimple.java"); + } + + @TestMetadata("OverriddenAmbiguousAdapters.java") + public void testOverriddenAmbiguousAdapters() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/sam/adapters/inheritance/OverriddenAmbiguousAdapters.java"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("Adapters"); + suite.addTestSuite(Adapters.class); + suite.addTestSuite(Inheritance.class); + return suite; + } } public static Test innerSuite() { TestSuite suite = new TestSuite("Sam"); suite.addTestSuite(Sam.class); - suite.addTestSuite(Adapters.class); + suite.addTest(Adapters.innerSuite()); return suite; } } @@ -1422,6 +1482,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/javaAgainstKotlin/samAdapters"), Pattern.compile("^(.+)\\.txt$"), true); } + @TestMetadata("InheritAmbguousSamAdaptersInKotlin.txt") + public void testInheritAmbguousSamAdaptersInKotlin() throws Exception { + doTestJavaAgainstKotlin("compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritAmbguousSamAdaptersInKotlin.txt"); + } + @TestMetadata("InheritSamAdapterInKotlin.txt") public void testInheritSamAdapterInKotlin() throws Exception { doTestJavaAgainstKotlin("compiler/testData/loadJava/javaAgainstKotlin/samAdapters/InheritSamAdapterInKotlin.txt"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index 4e5a10b0deb..4eb05ca9dc4 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -446,6 +446,21 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/fun"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("InheritMethodsDifferentReturnTypesAndVisibilities.kt") + public void testInheritMethodsDifferentReturnTypesAndVisibilities() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt"); + } + + @TestMetadata("InheritValAndVar.kt") + public void testInheritValAndVar() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/fun/InheritValAndVar.kt"); + } + + @TestMetadata("InheritValsDifferentTypes.kt") + public void testInheritValsDifferentTypes() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/fun/InheritValsDifferentTypes.kt"); + } + @TestMetadata("NoSamAdapter.kt") public void testNoSamAdapter() throws Exception { doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/fun/NoSamAdapter.kt"); @@ -1186,6 +1201,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/FinalFieldAsVal.kt"); } + @TestMetadata("InheritMethodsDifferentReturnTypes.kt") + public void testInheritMethodsDifferentReturnTypes() throws Exception { + doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypes.kt"); + } + + @TestMetadata("InheritMethodsDifferentReturnTypesGeneric.kt") + public void testInheritMethodsDifferentReturnTypesGeneric() throws Exception { + doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/InheritMethodsDifferentReturnTypesGeneric.kt"); + } + @TestMetadata("InnerClass.kt") public void testInnerClass() throws Exception { doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/InnerClass.kt"); diff --git a/examples/src/actors/src/Actors.kt b/examples/src/actors/src/Actors.kt index b7c5ad69f3a..3c858b82829 100644 --- a/examples/src/actors/src/Actors.kt +++ b/examples/src/actors/src/Actors.kt @@ -39,9 +39,9 @@ abstract class Actor(protected val executor: Executor, val fair: Boolean = false } else { val removed = q.removeFirst() - val newQueue = if(removed._2.empty) busyEmptyQueue else removed._2 + val newQueue = if(removed.second.empty) busyEmptyQueue else removed.second if(compareAndSet(q, newQueue)) { - doProcess(removed._1) + doProcess(removed.first) executor.execute(this) break } diff --git a/generators/org/jetbrains/jet/generators/tests/GenerateTests.java b/generators/org/jetbrains/jet/generators/tests/GenerateTests.java index d4c30962b2f..f2ec4c9a962 100644 --- a/generators/org/jetbrains/jet/generators/tests/GenerateTests.java +++ b/generators/org/jetbrains/jet/generators/tests/GenerateTests.java @@ -49,6 +49,7 @@ import org.jetbrains.jet.plugin.quickfix.AbstractQuickFixMultiFileTest; import org.jetbrains.jet.plugin.quickfix.AbstractQuickFixTest; import org.jetbrains.jet.psi.AbstractJetPsiMatcherTest; import org.jetbrains.jet.resolve.AbstractResolveTest; +import org.jetbrains.jet.safeDelete.AbstractJetSafeDeleteTest; import org.jetbrains.jet.test.generator.SimpleTestClassModel; import org.jetbrains.jet.test.generator.TestClassModel; import org.jetbrains.jet.test.generator.TestGenerator; @@ -395,6 +396,17 @@ public class GenerateTests { AbstractJetQuickDocProviderTest.class, testModel("idea/testData/editor/quickDoc", "doTest") ); + + generateTest( + "idea/tests/", + "JetSafeDeleteTestGenerated", + AbstractJetSafeDeleteTest.class, + testModel("idea/testData/safeDelete/deleteClass", "doClassTest"), + testModel("idea/testData/safeDelete/deleteObject", "doObjectTest"), + testModel("idea/testData/safeDelete/deleteFunction", "doFunctionTest"), + testModel("idea/testData/safeDelete/deleteFunctionWithJavaUsages", "doFunctionTestWithJava"), + testModel("idea/testData/safeDelete/deleteJavaMethod", "doJavaMethodTest") + ); } private static SimpleTestClassModel testModel(@NotNull String rootPath) { diff --git a/idea/idea.iml b/idea/idea.iml index 827ac8384c5..698be01ed13 100644 --- a/idea/idea.iml +++ b/idea/idea.iml @@ -26,6 +26,7 @@ + @@ -33,6 +34,8 @@ + + diff --git a/idea/src/META-INF/junit.xml b/idea/src/META-INF/junit.xml new file mode 100644 index 00000000000..aee3e23b3ad --- /dev/null +++ b/idea/src/META-INF/junit.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index a2267f5431f..5e148a1b506 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -8,7 +8,8 @@ - JUnit + JUnit + TestNG-J com.intellij.copyright @@ -52,6 +53,7 @@ + - @@ -226,6 +227,11 @@ order="first"/> + + diff --git a/idea/src/META-INF/testng-j.xml b/idea/src/META-INF/testng-j.xml new file mode 100644 index 00000000000..244886763ef --- /dev/null +++ b/idea/src/META-INF/testng-j.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 3fd4c5848b8..b2d2d9f78db 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -232,4 +232,30 @@ add.function.to.type.action.type.chooser=Choose type... remove.expression = Remove ''{0}'' unwrap.expression = Unwrap ''{0}'' remove.else = Remove else in ''{0}'' -unwrap.else = Unwrap else in ''{0}'' \ No newline at end of file +unwrap.else = Unwrap else in ''{0}'' + +usageType.annotation.type = Annotation +usageType.import = Import directive +usageType.callable.reference = Callable reference +usageType.type.constraint = Type constraint +usageType.type.argument = Type argument +usageType.value.parameter.type = Parameter type +usageType.nonLocal.property.type = Class/object property type +usageType.local.variable.type = Local variable type +usageType.function.return.type = Function return types +usageType.superType = Supertype +usageType.type.definition = Type definition +usageType.is = Target type of 'is' operation +usageType.as = Target type of 'as' operation +usageType.class.object = Nested class/object +usageType.instantiation = Instantiation +usageType.function.call = Function call +usageType.extension.receiver.type = Extension receiver type +usageType.super.type.qualifier = Super type qualifier +usageType.receiver = Receiver +usageType.selector = Selector + +x.in.y={0} in {1} +x.implements.y={0} in {1} implements {2} in {3}. +x.overrides.y.in.class.list={0} in {1} overrides functions in the following classes/traits: {2} Do you want to delete (with usage search) the base methods? +unused.overriding.methods.title=Unused Overriding Methods \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java index 1e81b14fa56..16902a3b4ed 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java @@ -47,9 +47,15 @@ public abstract class AbstractJetUpDownMover extends LineMover { LineRange lineRange2 = getElementSourceLineRange(combinedRange.second, editor, oldRange); if (lineRange2 == null) return null; + LineRange parentLineRange = getElementSourceLineRange(parent, editor, oldRange); + LineRange sourceRange = new LineRange(lineRange1.startLine, lineRange2.endLine); - sourceRange.firstElement = combinedRange.first; - sourceRange.lastElement = combinedRange.second; + if (parentLineRange != null && sourceRange.contains(parentLineRange)) { + sourceRange.firstElement = sourceRange.lastElement = parent; + } else { + sourceRange.firstElement = combinedRange.first; + sourceRange.lastElement = combinedRange.second; + } return sourceRange; } diff --git a/idea/src/org/jetbrains/jet/plugin/findUsages/JetElementDescriptionProvider.java b/idea/src/org/jetbrains/jet/plugin/findUsages/JetElementDescriptionProvider.java index 9f8801e79aa..7075cdcdc5e 100644 --- a/idea/src/org/jetbrains/jet/plugin/findUsages/JetElementDescriptionProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/findUsages/JetElementDescriptionProvider.java @@ -20,9 +20,10 @@ import com.intellij.psi.ElementDescriptionLocation; import com.intellij.psi.ElementDescriptionProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; +import com.intellij.refactoring.util.RefactoringDescriptionLocation; import com.intellij.usageView.UsageViewLongNameLocation; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.*; public class JetElementDescriptionProvider implements ElementDescriptionProvider { @Override @@ -32,6 +33,21 @@ public class JetElementDescriptionProvider implements ElementDescriptionProvider return ((PsiNamedElement)element).getName(); } } + else if (location instanceof RefactoringDescriptionLocation) { + if (element instanceof JetClass) { + JetClass jetClass = (JetClass) element; + return (jetClass.isTrait() ? "Trait " : "Class ") + jetClass.getName(); + } + if (element instanceof JetObjectDeclaration || element instanceof JetObjectDeclarationName) { + return "Object " + ((PsiNamedElement)element).getName(); + } + if (element instanceof JetNamedFunction) { + return "Function " + ((PsiNamedElement)element).getName(); + } + if (element instanceof JetProperty) { + return "Property " + ((PsiNamedElement)element).getName(); + } + } return null; } } diff --git a/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.java b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.java new file mode 100644 index 00000000000..2b433894130 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.java @@ -0,0 +1,219 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.findUsages; + +import com.google.common.base.Predicate; +import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.usages.UsageTarget; +import com.intellij.usages.impl.rules.UsageType; +import com.intellij.usages.impl.rules.UsageTypeProviderEx; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lexer.JetTokens; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; + +public class JetUsageTypeProvider implements UsageTypeProviderEx { + private static final Predicate IS_ASSIGNMENT = new Predicate() { + @Override + public boolean apply(@Nullable PsiElement input) { + return input != null && JetPsiUtil.isAssignment(input); + } + }; + + @Nullable + @Override + public UsageType getUsageType(PsiElement element) { + return getUsageType(element, UsageTarget.EMPTY_ARRAY); + } + + @Nullable + @Override + public UsageType getUsageType(PsiElement element, @NotNull UsageTarget[] targets) { + if (element == null) return null; + + UsageType usageType = getCommonUsageType(element); + if (usageType != null) return usageType; + + JetSimpleNameExpression reference = PsiTreeUtil.getParentOfType(element, JetSimpleNameExpression.class, false); + if (reference == null) return null; + + BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) element.getContainingFile()).getBindingContext(); + DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, reference); + + if (descriptor instanceof ClassifierDescriptor) { + return getClassUsageType(element); + } + if (descriptor instanceof VariableDescriptor) { + return getVariableUsageType(element); + } + if (descriptor instanceof FunctionDescriptor) { + return getFunctionUsageType(element, (FunctionDescriptor) descriptor); + } + + return null; + } + + private static UsageType getCommonUsageType(@NotNull PsiElement element) { + JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false); + if (importDirective != null) return JetUsageTypes.IMPORT_DIRECTIVE; + + JetCallableReferenceExpression callableReference = + PsiTreeUtil.getParentOfType(element, JetCallableReferenceExpression.class, false); + if (callableReference != null && PsiTreeUtil.isAncestor(callableReference.getCallableReference(), element, false)) { + return JetUsageTypes.CALLABLE_REFERENCE; + } + + return null; + } + + @Nullable + private static UsageType getClassUsageType(@NotNull PsiElement element) { + JetTypeParameter typeParameter = PsiTreeUtil.getParentOfType(element, JetTypeParameter.class, false); + if (typeParameter != null && PsiTreeUtil.isAncestor(typeParameter.getExtendsBound(), element, false)) { + return JetUsageTypes.TYPE_CONSTRAINT; + } + + JetTypeConstraint typeConstraint = PsiTreeUtil.getParentOfType(element, JetTypeConstraint.class, false); + if (typeConstraint != null && PsiTreeUtil.isAncestor(typeConstraint.getBoundTypeReference(), element, false)) { + return JetUsageTypes.TYPE_CONSTRAINT; + } + + JetDelegationSpecifier delegationSpecifier = PsiTreeUtil.getParentOfType(element, JetDelegationSpecifier.class, false); + if (delegationSpecifier != null + && (delegationSpecifier == element || PsiTreeUtil.isAncestor(delegationSpecifier.getTypeReference(), element, false))) { + return JetUsageTypes.SUPER_TYPE; + } + + JetTypedef typedef = PsiTreeUtil.getParentOfType(element, JetTypedef.class, false); + if (typedef != null && PsiTreeUtil.isAncestor(typedef.getTypeReference(), element, false)) { + return JetUsageTypes.TYPE_DEFINITION; + } + + JetTypeProjection typeProjection = PsiTreeUtil.getParentOfType(element, JetTypeProjection.class, false); + if (typeProjection != null) return JetUsageTypes.TYPE_ARGUMENT; + + JetParameter parameter = PsiTreeUtil.getParentOfType(element, JetParameter.class, false); + if (parameter != null) { + if (PsiTreeUtil.isAncestor(parameter.getTypeReference(), element, false)) return JetUsageTypes.VALUE_PARAMETER_TYPE; + } + + JetProperty property = PsiTreeUtil.getParentOfType(element, JetProperty.class, false); + if (property != null) { + if (PsiTreeUtil.isAncestor(property.getTypeRef(), element, false)) { + return property.isLocal() ? JetUsageTypes.LOCAL_VARIABLE_TYPE : JetUsageTypes.NON_LOCAL_PROPERTY_TYPE; + } + if (PsiTreeUtil.isAncestor(property.getReceiverTypeRef(), element, false)) { + return JetUsageTypes.EXTENSION_RECEIVER_TYPE; + } + } + + JetFunction function = PsiTreeUtil.getParentOfType(element, JetFunction.class, false); + if (function != null) { + if (PsiTreeUtil.isAncestor(function.getReturnTypeRef(), element, false)) { + return JetUsageTypes.FUNCTION_RETURN_TYPE; + } + if (PsiTreeUtil.isAncestor(function.getReceiverTypeRef(), element, false)) { + return JetUsageTypes.EXTENSION_RECEIVER_TYPE; + } + } + + JetIsExpression isExpression = PsiTreeUtil.getParentOfType(element, JetIsExpression.class, false); + if (isExpression != null && PsiTreeUtil.isAncestor(isExpression.getTypeRef(), element, false)) { + return JetUsageTypes.IS; + } + + JetBinaryExpressionWithTypeRHS typeRHSExpression = + PsiTreeUtil.getParentOfType(element, JetBinaryExpressionWithTypeRHS.class, false); + if (typeRHSExpression != null && PsiTreeUtil.isAncestor(typeRHSExpression.getRight(), element, false)) { + IElementType opType = typeRHSExpression.getOperationReference().getReferencedNameElementType(); + if (opType == JetTokens.AS_KEYWORD || opType == JetTokens.AS_SAFE) return JetUsageTypes.AS; + } + + JetDotQualifiedExpression dotQualifiedExpression = PsiTreeUtil.getParentOfType(element, JetDotQualifiedExpression.class, false); + if (dotQualifiedExpression != null + && dotQualifiedExpression.getReceiverExpression() instanceof JetSimpleNameExpression + && PsiTreeUtil.isAncestor(dotQualifiedExpression.getReceiverExpression(), element, false)) { + + return JetUsageTypes.CLASS_OBJECT_ACCESS; + } + + JetSuperExpression superExpression = PsiTreeUtil.getParentOfType(element, JetSuperExpression.class, false); + if (superExpression != null && PsiTreeUtil.isAncestor(superExpression.getSuperTypeQualifier(), element, false)) { + return JetUsageTypes.SUPER_TYPE_QUALIFIER; + } + + return null; + } + + @Nullable + private static UsageType getFunctionUsageType(@NotNull PsiElement element, @NotNull FunctionDescriptor descriptor) { + if (descriptor instanceof ConstructorDescriptor) { + JetAnnotationEntry annotation = PsiTreeUtil.getParentOfType(element, JetAnnotationEntry.class, false); + if (annotation != null && PsiTreeUtil.isAncestor(annotation.getTypeReference(), element, false)) { + return JetUsageTypes.ANNOTATION_TYPE; + } + } + + JetCallExpression callExpression = PsiTreeUtil.getParentOfType(element, JetCallExpression.class, false); + if (callExpression != null + && callExpression.getCalleeExpression() instanceof JetSimpleNameExpression + && PsiTreeUtil.isAncestor(callExpression.getCalleeExpression(), element, false)) { + + return (descriptor instanceof ConstructorDescriptor) ? JetUsageTypes.INSTANTIATION : JetUsageTypes.FUNCTION_CALL; + } + + return null; + } + + @Nullable + private static UsageType getVariableUsageType(@NotNull PsiElement element) { + JetDotQualifiedExpression dotQualifiedExpression = PsiTreeUtil.getParentOfType(element, JetDotQualifiedExpression.class, false); + if (dotQualifiedExpression != null) { + if (PsiTreeUtil.isAncestor(dotQualifiedExpression.getReceiverExpression(), element, false)) { + return JetUsageTypes.RECEIVER; + } + + PsiElement parent = dotQualifiedExpression.getParent(); + if (parent instanceof JetDotQualifiedExpression + && PsiTreeUtil.isAncestor(((JetDotQualifiedExpression) parent).getReceiverExpression(), element, false)) { + return JetUsageTypes.RECEIVER; + } + + return JetUsageTypes.SELECTOR; + } + + JetBinaryExpression binaryExpression = + (JetBinaryExpression) JetPsiUtil.getParentByTypeAndPredicate(element, JetBinaryExpression.class, IS_ASSIGNMENT, false); + if (binaryExpression != null && PsiTreeUtil.isAncestor(binaryExpression.getLeft(), element, false)) { + return UsageType.WRITE; + } + + JetSimpleNameExpression simpleNameExpression = PsiTreeUtil.getParentOfType(element, JetSimpleNameExpression.class, false); + if (simpleNameExpression != null) { + return UsageType.READ; + } + + return null; + } +} + diff --git a/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypes.java b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypes.java new file mode 100644 index 00000000000..4699d618bf8 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypes.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.findUsages; + +import com.intellij.usages.impl.rules.UsageType; +import org.jetbrains.jet.plugin.JetBundle; + +public class JetUsageTypes { + private JetUsageTypes() { + } + + // Type-related usages + public static final UsageType ANNOTATION_TYPE = new UsageType(JetBundle.message("usageType.annotation.type")); + public static final UsageType TYPE_CONSTRAINT = new UsageType(JetBundle.message("usageType.type.constraint")); + public static final UsageType TYPE_ARGUMENT = new UsageType(JetBundle.message("usageType.type.argument")); + public static final UsageType VALUE_PARAMETER_TYPE = new UsageType(JetBundle.message("usageType.value.parameter.type")); + public static final UsageType NON_LOCAL_PROPERTY_TYPE = new UsageType(JetBundle.message("usageType.nonLocal.property.type")); + public static final UsageType LOCAL_VARIABLE_TYPE = new UsageType(JetBundle.message("usageType.local.variable.type")); + public static final UsageType FUNCTION_RETURN_TYPE = new UsageType(JetBundle.message("usageType.function.return.type")); + public static final UsageType SUPER_TYPE = new UsageType(JetBundle.message("usageType.superType")); + public static final UsageType TYPE_DEFINITION = new UsageType(JetBundle.message("usageType.type.definition")); + public static final UsageType AS = new UsageType(JetBundle.message("usageType.as")); + public static final UsageType IS = new UsageType(JetBundle.message("usageType.is")); + public static final UsageType CLASS_OBJECT_ACCESS = new UsageType(JetBundle.message("usageType.class.object")); + public static final UsageType EXTENSION_RECEIVER_TYPE = new UsageType(JetBundle.message("usageType.extension.receiver.type")); + public static final UsageType SUPER_TYPE_QUALIFIER = new UsageType(JetBundle.message("usageType.super.type.qualifier")); + + // Function-related usages + public static final UsageType INSTANTIATION = new UsageType(JetBundle.message("usageType.instantiation")); + public static final UsageType FUNCTION_CALL = new UsageType(JetBundle.message("usageType.function.call")); + + // Value-related usages + public static final UsageType RECEIVER = new UsageType(JetBundle.message("usageType.receiver")); + public static final UsageType SELECTOR = new UsageType(JetBundle.message("usageType.selector")); + + // Miscellaneous usages + public static final UsageType IMPORT_DIRECTIVE = new UsageType(JetBundle.message("usageType.import")); + public static final UsageType CALLABLE_REFERENCE = new UsageType(JetBundle.message("usageType.callable.reference")); +} diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java index f6f40234e87..4e976396942 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java @@ -21,16 +21,21 @@ import com.intellij.psi.PsiElement; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetFunction; -import org.jetbrains.jet.lang.psi.JetProperty; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeSignatureHandler; import org.jetbrains.jet.plugin.refactoring.introduceVariable.JetIntroduceVariableHandler; +import org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinSafeDeleteProcessor; /** * User: Alefas * Date: 25.01.12 */ public class JetRefactoringSupportProvider extends RefactoringSupportProvider { + @Override + public boolean isSafeDeleteAvailable(PsiElement element) { + return KotlinSafeDeleteProcessor.canDeleteElement(element); + } + @Override public RefactoringActionHandler getIntroduceVariableHandler() { return new JetIntroduceVariableHandler(); diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinOverridingMethodsDialog.java b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinOverridingMethodsDialog.java new file mode 100644 index 00000000000..f8016dbafce --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinOverridingMethodsDialog.java @@ -0,0 +1,295 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.refactoring.safeDelete; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.help.HelpManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.Disposer; +import com.intellij.psi.PsiMethod; +import com.intellij.refactoring.HelpID; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.ui.BooleanTableCellRenderer; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.usageView.UsageInfo; +import com.intellij.usages.impl.UsagePreviewPanel; +import com.intellij.ui.table.JBTable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JetClsMethod; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.renderer.DescriptorRenderer; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableColumnModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/* +* Mostly copied from com.intellij.refactoring.safeDelete.OverridingMethodsDialog +* Revision: 14aa2e2 +* (replace PsiMethod formatting) +*/ +class KotlinOverridingMethodsDialog extends DialogWrapper { + private final List myOverridingMethods; + private final String[] myMethodText; + private final boolean[] myChecked; + + private static final int CHECK_COLUMN = 0; + private JBTable myTable; + private final UsagePreviewPanel myUsagePreviewPanel; + + public KotlinOverridingMethodsDialog(Project project, List overridingMethods) { + super(project, true); + myOverridingMethods = overridingMethods; + myChecked = new boolean[myOverridingMethods.size()]; + for (int i = 0; i < myChecked.length; i++) { + myChecked[i] = true; + } + + myMethodText = new String[myOverridingMethods.size()]; + for (int i = 0; i < myMethodText.length; i++) { + myMethodText[i] = formatMethod(((KotlinSafeDeleteOverridingMethodUsageInfo) myOverridingMethods.get(i)).getOverridingMethod()); + } + myUsagePreviewPanel = new UsagePreviewPanel(project); + setTitle(JetBundle.message("unused.overriding.methods.title")); + init(); + } + + private static String formatMethod(PsiMethod method) { + if (method instanceof JetClsMethod) { + JetNamedFunction function = (JetNamedFunction) ((JetClsMethod) method).getOrigin(); + + BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) function.getContainingFile()).getBindingContext(); + + DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); + if (declarationDescriptor instanceof FunctionDescriptor) { + DeclarationDescriptor containingDescriptor = declarationDescriptor.getContainingDeclaration(); + if (containingDescriptor instanceof ClassDescriptor) { + return JetBundle.message( + "x.in.y", + DescriptorRenderer.COMPACT.render(declarationDescriptor), + DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(containingDescriptor) + ); + } + } + } + + return KotlinSafeDeleteProcessor.formatPsiMethod(method, true, false); + } + + @Override + protected String getDimensionServiceKey() { + return "#org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinOverridingMethodsDialog"; + } + + public ArrayList getSelected() { + ArrayList result = new ArrayList(); + for (int i = 0; i < myChecked.length; i++) { + if (myChecked[i]) { + result.add(myOverridingMethods.get(i)); + } + } + return result; + } + + @NotNull + @Override + protected Action[] createActions() { + return new Action[] {getOKAction(), getCancelAction()}; + } + + @Override + protected void doHelpAction() { + HelpManager.getInstance().invokeHelp(HelpID.SAFE_DELETE_OVERRIDING); + } + + @Override + protected JComponent createNorthPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.add(new JLabel(RefactoringBundle.message("there.are.unused.methods.that.override.methods.you.delete"))); + panel.add(new JLabel(RefactoringBundle.message("choose.the.ones.you.want.to.be.deleted"))); + return panel; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myTable; + } + + @Override + protected void dispose() { + Disposer.dispose(myUsagePreviewPanel); + super.dispose(); + } + + @Override + protected JComponent createCenterPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(8, 0, 4, 0)); + final MyTableModel tableModel = new MyTableModel(); + myTable = new JBTable(tableModel); + myTable.setShowGrid(false); + + TableColumnModel columnModel = myTable.getColumnModel(); + int checkBoxWidth = new JCheckBox().getPreferredSize().width; + columnModel.getColumn(CHECK_COLUMN).setCellRenderer(new BooleanTableCellRenderer()); + columnModel.getColumn(CHECK_COLUMN).setMaxWidth(checkBoxWidth); + columnModel.getColumn(CHECK_COLUMN).setMinWidth(checkBoxWidth); + + + // make SPACE check/uncheck selected rows + InputMap inputMap = myTable.getInputMap(); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "enable_disable"); + ActionMap actionMap = myTable.getActionMap(); + actionMap.put("enable_disable", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (myTable.isEditing()) return; + int[] rows = myTable.getSelectedRows(); + if (rows.length > 0) { + boolean valueToBeSet = false; + for (int row : rows) { + if (!myChecked[row]) { + valueToBeSet = true; + break; + } + } + for (int row : rows) { + myChecked[row] = valueToBeSet; + } + + tableModel.updateData(); + } + } + }); + + panel.setLayout(new BorderLayout()); + + JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable); + + panel.add(scrollPane, BorderLayout.CENTER); + ListSelectionListener selectionListener = new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + int index = myTable.getSelectionModel().getLeadSelectionIndex(); + if (index != -1) { + UsageInfo usageInfo = myOverridingMethods.get(index); + myUsagePreviewPanel.updateLayout(Collections.singletonList(usageInfo)); + } + else { + myUsagePreviewPanel.updateLayout(null); + } + } + }; + myTable.getSelectionModel().addListSelectionListener(selectionListener); + + final Splitter splitter = new Splitter(true, 0.3f); + splitter.setFirstComponent(panel); + splitter.setSecondComponent(myUsagePreviewPanel); + myUsagePreviewPanel.updateLayout(null); + + Disposer.register(myDisposable, new Disposable() { + @Override + public void dispose() { + splitter.dispose(); + } + }); + + if (tableModel.getRowCount() != 0) { + myTable.getSelectionModel().addSelectionInterval(0, 0); + } + return splitter; + } + + class MyTableModel extends AbstractTableModel { + @Override + public int getRowCount() { + return myChecked.length; + } + + @Override + public String getColumnName(int column) { + switch (column) { + case CHECK_COLUMN: + return " "; + default: + return RefactoringBundle.message("method.column"); + } + } + + @Override + public Class getColumnClass(int columnIndex) { + switch (columnIndex) { + case CHECK_COLUMN: + return Boolean.class; + default: + return String.class; + } + } + + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if (columnIndex == CHECK_COLUMN) { + return Boolean.valueOf(myChecked[rowIndex]); + } + else { + return myMethodText[rowIndex]; + } + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if (columnIndex == CHECK_COLUMN) { + myChecked[rowIndex] = ((Boolean) aValue).booleanValue(); + } + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex == CHECK_COLUMN; + } + + void updateData() { + fireTableDataChanged(); + } + } +} + diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteOverridingMethodUsageInfo.java b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteOverridingMethodUsageInfo.java new file mode 100644 index 00000000000..77e48b30ca6 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteOverridingMethodUsageInfo.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.refactoring.safeDelete; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteCustomUsageInfo; +import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteUsageInfo; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.jet.asJava.LightClassUtil; +import org.jetbrains.jet.lang.psi.JetNamedFunction; + +public class KotlinSafeDeleteOverridingMethodUsageInfo extends SafeDeleteUsageInfo implements SafeDeleteCustomUsageInfo { + public KotlinSafeDeleteOverridingMethodUsageInfo(PsiElement overridingMethod, PsiElement method) { + super(toPsiMethod(overridingMethod), toPsiMethod(method)); + } + + protected static PsiMethod toPsiMethod(PsiElement element) { + if (element instanceof JetNamedFunction) { + element = LightClassUtil.getLightClassMethod((JetNamedFunction) element); + } + return element instanceof PsiMethod ? (PsiMethod) element : null; + } + + public PsiMethod getOverridingMethod() { + return toPsiMethod(getElement()); + } + + @Override + public void performRefactoring() throws IncorrectOperationException { + PsiElement element = getElement(); + if (element != null) { + element.delete(); + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java new file mode 100644 index 00000000000..6109a9426e7 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java @@ -0,0 +1,586 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.refactoring.safeDelete; + +import com.intellij.ide.IdeBundle; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.search.searches.SuperMethodsSearch; +import com.intellij.psi.util.*; +import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor; +import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo; +import com.intellij.refactoring.safeDelete.SafeDeleteProcessor; +import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo; +import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.*; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.asJava.LightClassUtil; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.Modality; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.java.JetClsMethod; +import org.jetbrains.jet.lexer.JetTokens; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.renderer.DescriptorRenderer; + +import java.util.*; + +public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { + public static boolean canDeleteElement(PsiElement element) { + return element instanceof JetClassOrObject + || element instanceof JetObjectDeclarationName + || element instanceof JetNamedFunction + || element instanceof PsiMethod; + } + + @Override + public boolean handlesElement(PsiElement element) { + return canDeleteElement(element); + } + + protected static NonCodeUsageSearchInfo getDefaultNonCodeUsageSearchInfo( + @NotNull PsiElement element, @NotNull PsiElement[] allElementsToDelete + ) { + return new NonCodeUsageSearchInfo(SafeDeleteProcessor.getDefaultInsideDeletedCondition(allElementsToDelete), element); + } + + @Nullable + @Override + public NonCodeUsageSearchInfo findUsages(PsiElement element, PsiElement[] allElementsToDelete, List result) { + if (element instanceof JetClassOrObject) { + return findClassOrObjectUsages(element, (JetClassOrObject) element, allElementsToDelete, result); + } + if (element instanceof JetObjectDeclarationName) { + PsiElement parent = getObjectDeclarationOrFail(element); + return findClassOrObjectUsages(element, (JetObjectDeclaration) parent, allElementsToDelete, result); + } + if (element instanceof JetNamedFunction) { + return findFunctionUsages((JetNamedFunction) element, allElementsToDelete, result); + } + if (element instanceof PsiMethod) { + return findPsiMethodUsages((PsiMethod) element, allElementsToDelete, result); + } + return getDefaultNonCodeUsageSearchInfo(element, allElementsToDelete); + } + + private static PsiElement getObjectDeclarationOrFail(PsiElement element) { + PsiElement parent = element.getParent(); + assert parent instanceof JetObjectDeclaration; + return parent; + } + + @SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass") + protected static boolean isInside(PsiElement place, PsiElement[] ancestors) { + return isInside(place, Arrays.asList(ancestors)); + } + + @SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass") + protected static boolean isInside(PsiElement place, Collection ancestors) { + for (PsiElement element : ancestors) { + if (isInside(place, element)) return true; + } + return false; + } + + @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass") + public static boolean isInside(PsiElement place, PsiElement ancestor) { + if (ancestor instanceof JetClsMethod) { + ancestor = ((JetClsMethod) ancestor).getOrigin(); + } + return JavaSafeDeleteProcessor.isInside(place, ancestor); + } + + protected static NonCodeUsageSearchInfo findClassOrObjectUsages( + PsiElement referencedElement, + final JetClassOrObject classOrObject, + final PsiElement[] allElementsToDelete, + final List result + ) { + ReferencesSearch.search(referencedElement).forEach(new Processor() { + @Override + public boolean process(PsiReference reference) { + PsiElement element = reference.getElement(); + + if (!isInside(element, allElementsToDelete)) { + JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false); + if (importDirective != null) { + result.add(new SafeDeleteImportDirectiveUsageInfo(importDirective, classOrObject)); + return true; + } + + result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, classOrObject, false)); + } + return true; + } + }); + + return getDefaultNonCodeUsageSearchInfo(referencedElement, allElementsToDelete); + } + + protected NonCodeUsageSearchInfo findPsiMethodUsages( + PsiMethod method, + PsiElement[] allElementsToDelete, + List result + ) { + List javaUsages = new ArrayList(); + NonCodeUsageSearchInfo searchInfo = super.findUsages(method, allElementsToDelete, javaUsages); + + for (UsageInfo usageInfo : javaUsages) { + if (usageInfo instanceof SafeDeleteOverridingMethodUsageInfo) { + SafeDeleteOverridingMethodUsageInfo overrideUsageInfo = (SafeDeleteOverridingMethodUsageInfo) usageInfo; + usageInfo = new KotlinSafeDeleteOverridingMethodUsageInfo( + overrideUsageInfo.getSmartPointer().getElement(), overrideUsageInfo.getReferencedElement() + ); + } + result.add(usageInfo); + } + + return searchInfo; + } + + private static List difference(Collection from, T[] a) { + List list = new ArrayList(from); + list.removeAll(Arrays.asList(a)); + return list; + } + + protected static NonCodeUsageSearchInfo findFunctionUsages( + JetNamedFunction function, + final PsiElement[] allElementsToDelete, + List result + ) { + PsiMethod lightMethod = LightClassUtil.getLightClassMethod(function); + if (lightMethod == null) { + return getDefaultNonCodeUsageSearchInfo(function, allElementsToDelete); + } + + Collection references = ReferencesSearch.search(function).findAll(); + List overridingMethods = difference(OverridingMethodsSearch.search(lightMethod, true).findAll(), allElementsToDelete); + + for (PsiReference reference : references) { + PsiElement element = reference.getElement(); + if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) { + JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false); + if (importDirective != null) { + result.add(new SafeDeleteImportDirectiveUsageInfo(importDirective, function)); + } + else { + result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, function, false)); + } + } + } + + HashMap> methodToReferences = new HashMap>(); + for (PsiMethod overridingMethod : overridingMethods) { + Collection overridingReferences = + ReferencesSearch.search( + overridingMethod instanceof JetClsMethod ? ((JetClsMethod) overridingMethod).getOrigin() : overridingMethod + ).findAll(); + methodToReferences.put(overridingMethod, overridingReferences); + } + final Set safeOverriding = + filterSafeOverridingMethods(lightMethod, references, overridingMethods, methodToReferences, result, allElementsToDelete); + + return new NonCodeUsageSearchInfo( + new Condition() { + @Override + public boolean value(PsiElement usage) { + if (usage instanceof JetFile) return false; + return isInside(usage, allElementsToDelete) || isInside(usage, safeOverriding); + } + }, + function + ); + } + + /* + * Mostly copied from JavaSafeDeleteProcessor.validateOverridingMethods + * Revision: d4fc033 + * (simplified and implemented proper treatment of light methods) + */ + private static Set filterSafeOverridingMethods( + PsiMethod originalMethod, Collection originalReferences, + Collection overridingMethods, HashMap> methodToReferences, + List usages, + PsiElement[] allElementsToDelete + ) { + Set validOverriding = new LinkedHashSet(overridingMethods); + boolean anyNewBadRefs; + do { + anyNewBadRefs = false; + for (PsiMethod overridingMethod : overridingMethods) { + if (validOverriding.contains(overridingMethod)) { + Collection overridingReferences = methodToReferences.get(overridingMethod); + boolean anyOverridingRefs = false; + for (PsiReference overridingReference : overridingReferences) { + PsiElement element = overridingReference.getElement(); + if (!isInside(element, allElementsToDelete) && !isInside(element, validOverriding)) { + anyOverridingRefs = true; + break; + } + } + + if (!anyOverridingRefs && isMultipleInterfacesImplementation(overridingMethod, originalMethod, allElementsToDelete)) { + anyOverridingRefs = true; + } + + if (anyOverridingRefs) { + validOverriding.remove(overridingMethod); + anyNewBadRefs = true; + + for (PsiReference reference : originalReferences) { + PsiElement element = reference.getElement(); + if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) { + validOverriding.clear(); + } + } + } + } + } + } + while (anyNewBadRefs && !validOverriding.isEmpty()); + + for (PsiMethod method : validOverriding) { + if (method != originalMethod) { + usages.add(new KotlinSafeDeleteOverridingMethodUsageInfo(method, originalMethod)); + } + } + + return validOverriding; + } + + @SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass") + private static boolean isMultipleInterfacesImplementation(PsiMethod method, PsiMethod originalMethod, PsiElement[] ignore) { + PsiMethod[] methods = method.findSuperMethods(); + for (PsiMethod superMethod: methods) { + PsiElement relevantElement = superMethod instanceof JetClsMethod ? ((JetClsMethod) superMethod).getOrigin() : superMethod; + if (ArrayUtilRt.find(ignore, relevantElement) < 0 && !MethodSignatureUtil.isSuperMethod(originalMethod, superMethod)) { + return true; + } + } + return false; + } + + + private static String wrapOrSkip(String s, boolean inCode) { + return inCode ? "" + s + "" : s; + } + + private static String formatClass(DeclarationDescriptor classDescriptor, BindingContext bindingContext, boolean inCode) { + PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, classDescriptor); + if (element instanceof PsiClass) { + return formatPsiClass((PsiClass) element, false, inCode); + } + + return wrapOrSkip(formatClassDescriptor(classDescriptor), inCode); + } + + private static String formatFunction(DeclarationDescriptor functionDescriptor, BindingContext bindingContext, boolean inCode) { + PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, functionDescriptor); + if (element instanceof PsiMethod) { + return formatPsiMethod((PsiMethod) element, false, inCode); + } + + return wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode); + } + + private static String formatClassDescriptor(DeclarationDescriptor classDescriptor) { + return DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor); + } + + private static String formatFunctionDescriptor(DeclarationDescriptor functionDescriptor) { + return DescriptorRenderer.COMPACT.render(functionDescriptor); + } + + public static String formatPsiClass(PsiClass psiClass, boolean markAsJava, boolean inCode) { + String description; + + String kind = psiClass.isInterface() ? "interface " : "class "; + description = kind + PsiFormatUtil.formatClass( + psiClass, + PsiFormatUtilBase.SHOW_CONTAINING_CLASS + | PsiFormatUtilBase.SHOW_NAME + | PsiFormatUtilBase.SHOW_PARAMETERS + | PsiFormatUtilBase.SHOW_TYPE + ); + description = wrapOrSkip(description, inCode); + + return markAsJava ? "[Java] " + description : description; + } + + public static String formatPsiMethod(PsiMethod psiMethod, boolean showContainingClass, boolean inCode) { + int options = PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE; + if (showContainingClass) { + options |= PsiFormatUtilBase.SHOW_CONTAINING_CLASS; + } + + String description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE); + description = wrapOrSkip(description, inCode); + + return "[Java] " + description; + } + + @Override + public Collection findConflicts(PsiElement element, PsiElement[] allElementsToDelete) { + if (element instanceof JetNamedFunction) { + JetClass jetClass = PsiTreeUtil.getParentOfType(element, JetClass.class); + if (jetClass == null || jetClass.getBody() != element.getParent()) return null; + + JetModifierList modifierList = jetClass.getModifierList(); + if (modifierList != null && modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) return null; + + BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) element.getContainingFile()).getBindingContext(); + + DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); + if (!(declarationDescriptor instanceof FunctionDescriptor)) return null; + + List messages = new ArrayList(); + FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor; + for (FunctionDescriptor overridenDescriptor : functionDescriptor.getOverriddenDescriptors()) { + if (overridenDescriptor.getModality() == Modality.ABSTRACT) { + String message = JetBundle.message( + "x.implements.y", + formatFunction(functionDescriptor, bindingContext, true), + formatClass(functionDescriptor.getContainingDeclaration(), bindingContext, true), + formatFunction(overridenDescriptor, bindingContext, true), + formatClass(overridenDescriptor.getContainingDeclaration(), bindingContext, true) + ); + messages.add(message); + } + } + + if (!messages.isEmpty()) return messages; + } + return super.findConflicts(element, allElementsToDelete); + } + + /* + * Mostly copied from JavaSafeDeleteProcessor.preprocessUsages + * Revision: d4fc033 + * (replaced original dialog) + */ + @Nullable + @Override + public UsageInfo[] preprocessUsages(Project project, UsageInfo[] usages) { + ArrayList result = new ArrayList(); + ArrayList overridingMethodUsages = new ArrayList(); + + for (UsageInfo usage : usages) { + if (usage instanceof KotlinSafeDeleteOverridingMethodUsageInfo) { + overridingMethodUsages.add(usage); + } + else { + result.add(usage); + } + } + + if (!overridingMethodUsages.isEmpty()) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + result.addAll(overridingMethodUsages); + } + else { + KotlinOverridingMethodsDialog dialog = new KotlinOverridingMethodsDialog(project, overridingMethodUsages); + dialog.show(); + if (!dialog.isOK()) return null; + result.addAll(dialog.getSelected()); + } + } + + return result.toArray(new UsageInfo[result.size()]); + } + + private static void removeOverrideModifier(@NotNull PsiElement element) { + if (element instanceof JetNamedFunction) { + JetModifierList modifierList = ((JetNamedFunction) element).getModifierList(); + if (modifierList == null) return; + + PsiElement overrideModifier = modifierList.getModifier(JetTokens.OVERRIDE_KEYWORD); + if (overrideModifier != null) { + overrideModifier.delete(); + } + } + else if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod) element; + + PsiAnnotation overrideAnnotation = null; + for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) { + if ("java.lang.Override".equals(annotation.getQualifiedName())) { + overrideAnnotation = annotation; + break; + } + } + + if (overrideAnnotation != null) { + overrideAnnotation.delete(); + } + } + } + + @Override + public void prepareForDeletion(PsiElement element) throws IncorrectOperationException { + if (element instanceof PsiMethod) { + cleanUpOverrides((PsiMethod) element); + } + else if (element instanceof JetNamedFunction) { + PsiMethod lightMethod = LightClassUtil.getLightClassMethod((JetNamedFunction) element); + if (lightMethod == null) { + return; + } + + cleanUpOverrides(lightMethod); + } + } + + private static void cleanUpOverrides(PsiMethod method) { + Collection superMethods = + SuperMethodsSearch.search(method, null, true, false).findAll(); + Collection overridingMethods = OverridingMethodsSearch.search(method, false).findAll(); + overrideLoop: for (PsiMethod overridingMethod : overridingMethods) { + PsiElement overridingElement = overridingMethod instanceof JetClsMethod + ? ((JetClsMethod) overridingMethod).getOrigin() + : overridingMethod; + Collection currentSuperMethods = + SuperMethodsSearch.search(overridingMethod, null, true, false).findAll(); + currentSuperMethods.addAll(superMethods); + for (MethodSignatureBackedByPsiMethod superMethod: currentSuperMethods) { + if (superMethod.getMethod() != method) continue overrideLoop; + } + + removeOverrideModifier(overridingElement); + } + } + + @Nullable + private static Collection checkSuperMethods( + @NotNull JetNamedFunction function, @Nullable Collection ignore + ) { + final BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) function.getContainingFile()).getBindingContext(); + + DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); + if (!(declarationDescriptor instanceof FunctionDescriptor)) return null; + + FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor; + Set overridenDescriptors = functionDescriptor.getOverriddenDescriptors(); + + Collection superMethods = ContainerUtil.map( + overridenDescriptors, + new Function() { + @Override + public PsiElement fun(FunctionDescriptor descriptor) { + return BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); + } + } + ); + if (ignore != null) { + superMethods.removeAll(ignore); + } + + if (superMethods.isEmpty()) return Collections.singletonList(function); + + List superClasses = ContainerUtil.map( + superMethods, + new Function() { + @Override + public String fun(PsiElement element) { + String description; + + if (element instanceof JetNamedFunction) { + DeclarationDescriptor descriptor = + bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); + assert descriptor != null; + + DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration(); + assert containingDescriptor != null; + + description = formatClassDescriptor(containingDescriptor); + } + else { + assert element instanceof PsiMethod; + + PsiClass psiClass = ((PsiMethod) element).getContainingClass(); + assert psiClass != null; + + description = formatPsiClass(psiClass, true, false); + } + + return " " + description + "\n"; + } + } + ); + + String superClassesStr = "\n" + StringUtil.join(superClasses, ""); + String message = JetBundle.message( + "x.overrides.y.in.class.list", + DescriptorRenderer.COMPACT.render(functionDescriptor), + DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(functionDescriptor.getContainingDeclaration()), + superClassesStr + ); + + int exitCode = Messages.showYesNoCancelDialog( + function.getProject(), message, IdeBundle.message("title.warning"), Messages.getQuestionIcon() + ); + switch (exitCode) { + case Messages.YES: + return superMethods; + case Messages.NO: + return Collections.singletonList(function); + default: + return Collections.emptyList(); + } + } + + @Nullable + @Override + public Collection getElementsToSearch( + PsiElement element, @Nullable Module module, Collection allElementsToDelete + ) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + return Collections.singletonList(element); + } + + if (element instanceof JetNamedFunction) { + return checkSuperMethods((JetNamedFunction) element, allElementsToDelete); + } + return super.getElementsToSearch(element, module, allElementsToDelete); + } + + @Override + public Collection getAdditionalElementsToDelete( + PsiElement element, Collection allElementsToDelete, boolean askUser + ) { + if (element instanceof JetObjectDeclarationName) { + return Arrays.asList(getObjectDeclarationOrFail(element)); + } + return super.getAdditionalElementsToDelete(element, allElementsToDelete, askUser); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/SafeDeleteImportDirectiveUsageInfo.java b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/SafeDeleteImportDirectiveUsageInfo.java new file mode 100644 index 00000000000..05e99fcb973 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/SafeDeleteImportDirectiveUsageInfo.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.refactoring.safeDelete; + +import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; + +public class SafeDeleteImportDirectiveUsageInfo extends SafeDeleteReferenceSimpleDeleteUsageInfo { + public SafeDeleteImportDirectiveUsageInfo(@NotNull JetImportDirective importDirective, @NotNull JetDeclaration declaration) { + super(importDirective, declaration, isSafeToDelete(declaration, importDirective)); + } + + private static boolean isSafeToDelete(@NotNull JetDeclaration declaration, @NotNull JetImportDirective importDirective) { + JetExpression importExpr = importDirective.getImportedReference(); + + JetReferenceExpression importReference = null; + if (importExpr instanceof JetSimpleNameExpression) { + importReference = (JetReferenceExpression) importExpr; + } + else if (importExpr instanceof JetDotQualifiedExpression) { + JetExpression selector = ((JetDotQualifiedExpression) importExpr).getSelectorExpression(); + if (selector instanceof JetSimpleNameExpression) { + importReference = (JetReferenceExpression) selector; + } + } + if (importReference == null) return false; + + BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) declaration.getContainingFile()).getBindingContext(); + + DeclarationDescriptor referenceDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, importReference); + + DeclarationDescriptor declarationDescriptor = declaration instanceof JetObjectDeclaration + ? bindingContext.get(BindingContext.OBJECT_DECLARATION, ((JetObjectDeclaration) declaration).getNameAsDeclaration()) + : bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); + + return referenceDescriptor == declarationDescriptor; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java b/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java index f728cea2367..f0c5381c9c0 100644 --- a/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java +++ b/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java @@ -114,7 +114,7 @@ public class JetJUnitConfigurationProducer extends RuntimeConfigurationProducer } @Nullable - private static JetClass getClassDeclarationInFile(JetFile jetFile) { + static JetClass getClassDeclarationInFile(JetFile jetFile) { JetClass tempSingleDeclaration = null; for (JetDeclaration jetDeclaration : jetFile.getDeclarations()) { diff --git a/idea/src/org/jetbrains/jet/plugin/run/JetTestNgConfigurationProducer.java b/idea/src/org/jetbrains/jet/plugin/run/JetTestNgConfigurationProducer.java new file mode 100644 index 00000000000..2709a0dace0 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/run/JetTestNgConfigurationProducer.java @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.run; + +import com.intellij.execution.JavaRunConfigurationExtensionManager; +import com.intellij.execution.Location; +import com.intellij.execution.PsiLocation; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiClassUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import com.theoryinpractice.testng.configuration.TestNGConfigurationProducer; +import com.theoryinpractice.testng.util.TestNGUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.asJava.LightClassUtil; +import org.jetbrains.jet.lang.psi.*; + +public class JetTestNgConfigurationProducer extends TestNGConfigurationProducer { + + public JetTestNgConfigurationProducer() { + super(); + } + + private JetElement myElement = null; + + @Override + public PsiElement getSourceElement() { + return myElement; + } + + @Override + @Nullable + protected RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext context) { + // TODO: check TestNG Pattern running first, before method/class (see TestNGInClassConfigurationProducer for logic) + // TODO: and PsiClassOwner not handled, which is in TestNGInClassConfigurationProducer + + Project project = location.getProject(); + PsiElement leaf = location.getPsiElement(); + + if (!(leaf.getContainingFile() instanceof JetFile)) { + return null; + } + + JetFile jetFile = (JetFile) leaf.getContainingFile(); + + JetNamedFunction function = PsiTreeUtil.getParentOfType(leaf, JetNamedFunction.class, false); + if (function != null) { + @SuppressWarnings("unchecked") + JetElement owner = PsiTreeUtil.getParentOfType(function, JetFunction.class, JetClass.class); + + if (owner instanceof JetClass) { + PsiClass delegate = LightClassUtil.getPsiClass((JetClass) owner); + if (delegate != null) { + for (PsiMethod method : delegate.getMethods()) { + if (method.getNavigationElement() == function) { + if (TestNGUtil.hasTest(method)) { + myElement = function; + return createRuntimeConfigSettings(location, context, project, delegate, method); + } + break; + } + } + } + } + } + + JetClass jetClass = PsiTreeUtil.getParentOfType(leaf, JetClass.class, false); + + if (jetClass == null) { + jetClass = JetJUnitConfigurationProducer.getClassDeclarationInFile(jetFile); + } + + if (jetClass == null) { + return null; + } + + PsiClass delegate = LightClassUtil.getPsiClass(jetClass); + if (!isTestNGClass(delegate)) { + return null; + } + + myElement = jetClass; + return createRuntimeConfigSettings(location, context, project, delegate, null); + } + + private RunnerAndConfigurationSettings createRuntimeConfigSettings( + Location location, ConfigurationContext context, Project project, + @Nullable PsiClass delegate, @Nullable PsiMethod method) { + if (delegate == null) { + return null; + } + + RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context); + TestNGConfiguration configuration = (TestNGConfiguration) settings.getConfiguration(); + setupConfigurationModule(context, configuration); + Module originalModule = configuration.getConfigurationModule().getModule(); + configuration.setClassConfiguration(delegate); + if (method != null) { + configuration.setMethodConfiguration(PsiLocation.fromPsiElement(project, method)); + } + configuration.restoreOriginalModule(originalModule); + settings.setName(configuration.getName()); + JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location); + return settings; + } + + private static boolean isTestNGClass(PsiClass psiClass) { + return psiClass != null && PsiClassUtil.isRunnableClass(psiClass, true, false) && TestNGUtil.hasTest(psiClass); + } + + @Override + public int compareTo(@NotNull Object o) { + return 0; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/search/KotlinReferencesSearcher.java b/idea/src/org/jetbrains/jet/plugin/search/KotlinReferencesSearcher.java index a1d59dd58f8..dcd74e77463 100644 --- a/idea/src/org/jetbrains/jet/plugin/search/KotlinReferencesSearcher.java +++ b/idea/src/org/jetbrains/jet/plugin/search/KotlinReferencesSearcher.java @@ -27,26 +27,33 @@ import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.asJava.LightClassUtil; -import org.jetbrains.jet.lang.psi.JetClass; -import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.psi.*; public class KotlinReferencesSearcher extends QueryExecutorBase { + public static void processJetClassOrObject( + final @NotNull JetClassOrObject element, @NotNull ReferencesSearch.SearchParameters queryParameters + ) { + String className = element.getName(); + if (className != null) { + PsiClass lightClass = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiClass compute() { + return LightClassUtil.getPsiClass(element); + } + }); + if (lightClass != null) { + queryParameters.getOptimizer().searchWord(className, queryParameters.getEffectiveSearchScope(), true, lightClass); + } + } + } + + + @Override public void processQuery(@NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull Processor consumer) { - final PsiElement element = queryParameters.getElementToSearch(); + PsiElement element = queryParameters.getElementToSearch(); if (element instanceof JetClass) { - String className = ((JetClass) element).getName(); - if (className != null) { - PsiClass lightClass = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public PsiClass compute() { - return LightClassUtil.getPsiClass((JetClass) element); - } - }); - if (lightClass != null) { - queryParameters.getOptimizer().searchWord(className, queryParameters.getEffectiveSearchScope(), true, lightClass); - } - } + processJetClassOrObject((JetClass) element, queryParameters); } else if (element instanceof JetNamedFunction) { final JetNamedFunction function = (JetNamedFunction) element; @@ -58,10 +65,33 @@ public class KotlinReferencesSearcher extends QueryExecutorBase() { + @Override + public LightClassUtil.PropertyAccessorsPsiMethods compute() { + return LightClassUtil.getLightClassPropertyMethods(property); + } + }); + + searchMethod(queryParameters, propertyMethods.getGetter()); + searchMethod(queryParameters, propertyMethods.getSetter()); + } + else if (element instanceof JetObjectDeclarationName) { + PsiElement parent = element.getParent(); + if (parent instanceof JetObjectDeclaration) { + processJetClassOrObject((JetObjectDeclaration)parent, queryParameters); } } } + + private static void searchMethod(ReferencesSearch.SearchParameters queryParameters, PsiMethod method) { + if (method != null) { + queryParameters.getOptimizer().searchWord(method.getName(), queryParameters.getEffectiveSearchScope(), true, method); + } + } } diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces1.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces1.kt new file mode 100644 index 00000000000..4fd37383aed --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces1.kt @@ -0,0 +1,7 @@ +// MOVE: down +fun main(args: Array) { +run { + println() +} + +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces1.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces1.kt.after new file mode 100644 index 00000000000..790e7ceca80 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces1.kt.after @@ -0,0 +1,7 @@ +// MOVE: down +fun main(args: Array) { + +run { + println() +} +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces2.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces2.kt new file mode 100644 index 00000000000..ba3a2a5e502 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces2.kt @@ -0,0 +1,7 @@ +// MOVE: up +fun main(args: Array) { + +run { + println() +} +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces2.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces2.kt.after new file mode 100644 index 00000000000..dafa58e2bff --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces2.kt.after @@ -0,0 +1,7 @@ +// MOVE: up +fun main(args: Array) { +run { + println() +} + +} \ No newline at end of file diff --git a/idea/testData/findUsages/findClassUsages/Client.java b/idea/testData/findUsages/findClassUsages/javaUsages/Client.java similarity index 100% rename from idea/testData/findUsages/findClassUsages/Client.java rename to idea/testData/findUsages/findClassUsages/javaUsages/Client.java diff --git a/idea/testData/findUsages/findClassUsages/Server.kt b/idea/testData/findUsages/findClassUsages/javaUsages/Server.kt similarity index 100% rename from idea/testData/findUsages/findClassUsages/Server.kt rename to idea/testData/findUsages/findClassUsages/javaUsages/Server.kt diff --git a/idea/testData/findUsages/findClassUsages/kotlinUsages1/Client.kt b/idea/testData/findUsages/findClassUsages/kotlinUsages1/Client.kt new file mode 100644 index 00000000000..b24ac3812cf --- /dev/null +++ b/idea/testData/findUsages/findClassUsages/kotlinUsages1/Client.kt @@ -0,0 +1,34 @@ +package client + +import server.Server + +class Client: Server { + var nextServer: Server? = null + val name = Server.NAME + + fun foo(s: Server) { + val server: Server = s + println("Server: $server") + } + + fun getNextServer(): Server? { + return nextServer + } + + override fun work() { + super.work() + println("Client") + } +} + +fun Client.bar(s: Server) { + foo(s) +} + +fun Client.hasNextServer(): Boolean { + return getNextServer() != null +} + +fun Any.asServer(): Server? { + return if (this is Server) this as Server else null +} \ No newline at end of file diff --git a/idea/testData/findUsages/findClassUsages/kotlinUsages1/Server.kt b/idea/testData/findUsages/findClassUsages/kotlinUsages1/Server.kt new file mode 100644 index 00000000000..e8f74cc9821 --- /dev/null +++ b/idea/testData/findUsages/findClassUsages/kotlinUsages1/Server.kt @@ -0,0 +1,11 @@ +package server + +open class Server { + class object { + val NAME = "Server" + } + + open fun work() { + println("Server") + } +} \ No newline at end of file diff --git a/idea/testData/findUsages/findClassUsages/kotlinUsages2/Client.kt b/idea/testData/findUsages/findClassUsages/kotlinUsages2/Client.kt new file mode 100644 index 00000000000..8511a3a9e92 --- /dev/null +++ b/idea/testData/findUsages/findClassUsages/kotlinUsages2/Client.kt @@ -0,0 +1,8 @@ +package client + +import server.X + +X("") +class Client { + +} \ No newline at end of file diff --git a/idea/testData/findUsages/findClassUsages/kotlinUsages2/Server.kt b/idea/testData/findUsages/findClassUsages/kotlinUsages2/Server.kt new file mode 100644 index 00000000000..92281e3ae02 --- /dev/null +++ b/idea/testData/findUsages/findClassUsages/kotlinUsages2/Server.kt @@ -0,0 +1,3 @@ +package server + +annotation class X(val x: String) \ No newline at end of file diff --git a/idea/testData/findUsages/findClassUsages/kotlinUsages3/Client.kt b/idea/testData/findUsages/findClassUsages/kotlinUsages3/Client.kt new file mode 100644 index 00000000000..92d7b496461 --- /dev/null +++ b/idea/testData/findUsages/findClassUsages/kotlinUsages3/Client.kt @@ -0,0 +1,9 @@ +package client + +import server.Data + +class Client where X: Data { + +} + +val c = Client() \ No newline at end of file diff --git a/idea/testData/findUsages/findClassUsages/kotlinUsages3/Server.kt b/idea/testData/findUsages/findClassUsages/kotlinUsages3/Server.kt new file mode 100644 index 00000000000..2b4068b1e88 --- /dev/null +++ b/idea/testData/findUsages/findClassUsages/kotlinUsages3/Server.kt @@ -0,0 +1,3 @@ +package server + +data class Data \ No newline at end of file diff --git a/idea/testData/findUsages/findMethodUsages/Client.java b/idea/testData/findUsages/findMethodUsages/javaUsages/Client.java similarity index 100% rename from idea/testData/findUsages/findMethodUsages/Client.java rename to idea/testData/findUsages/findMethodUsages/javaUsages/Client.java diff --git a/idea/testData/findUsages/findMethodUsages/Server.kt b/idea/testData/findUsages/findMethodUsages/javaUsages/Server.kt similarity index 100% rename from idea/testData/findUsages/findMethodUsages/Server.kt rename to idea/testData/findUsages/findMethodUsages/javaUsages/Server.kt diff --git a/idea/testData/findUsages/findMethodUsages/kotlinUsages/Client.kt b/idea/testData/findUsages/findMethodUsages/kotlinUsages/Client.kt new file mode 100644 index 00000000000..9bd981a0c77 --- /dev/null +++ b/idea/testData/findUsages/findMethodUsages/kotlinUsages/Client.kt @@ -0,0 +1,12 @@ +package client + +import server.processRequest + +class Client { + val methodRef = ::processRequest() + + fun doProcessRequest() { + println("Process...") + processRequest() + } +} \ No newline at end of file diff --git a/idea/testData/findUsages/findMethodUsages/kotlinUsages/Server.kt b/idea/testData/findUsages/findMethodUsages/kotlinUsages/Server.kt new file mode 100644 index 00000000000..4c303b09795 --- /dev/null +++ b/idea/testData/findUsages/findMethodUsages/kotlinUsages/Server.kt @@ -0,0 +1,4 @@ +package server; + +fun processRequest() = "foo" + diff --git a/idea/testData/findUsages/findObjectUsages/javaUsages/Client.java b/idea/testData/findUsages/findObjectUsages/javaUsages/Client.java new file mode 100644 index 00000000000..b896d9becc3 --- /dev/null +++ b/idea/testData/findUsages/findObjectUsages/javaUsages/Client.java @@ -0,0 +1,9 @@ +package client; + +import server.O + +class Client { + fun fooBar() { + println("foo = " + O.instance$.getFoo()) + } +} \ No newline at end of file diff --git a/idea/testData/findUsages/findObjectUsages/javaUsages/Server.kt b/idea/testData/findUsages/findObjectUsages/javaUsages/Server.kt new file mode 100644 index 00000000000..52c87b49e49 --- /dev/null +++ b/idea/testData/findUsages/findObjectUsages/javaUsages/Server.kt @@ -0,0 +1,6 @@ +package server; + +object O { + var foo: String = "foo" +} + diff --git a/idea/testData/findUsages/findObjectUsages/kotlinUsages/Client.kt b/idea/testData/findUsages/findObjectUsages/kotlinUsages/Client.kt new file mode 100644 index 00000000000..7b0126d1a91 --- /dev/null +++ b/idea/testData/findUsages/findObjectUsages/kotlinUsages/Client.kt @@ -0,0 +1,11 @@ +package client + +import server.O + +class Client { + fun fooBar() { + println("foo = ${O.foo}") + val obj = O + println("length: ${obj.foo.length()}") + } +} \ No newline at end of file diff --git a/idea/testData/findUsages/findObjectUsages/kotlinUsages/Server.kt b/idea/testData/findUsages/findObjectUsages/kotlinUsages/Server.kt new file mode 100644 index 00000000000..52c87b49e49 --- /dev/null +++ b/idea/testData/findUsages/findObjectUsages/kotlinUsages/Server.kt @@ -0,0 +1,6 @@ +package server; + +object O { + var foo: String = "foo" +} + diff --git a/idea/testData/findUsages/findPropertyUsages/javaUsages/Client.java b/idea/testData/findUsages/findPropertyUsages/javaUsages/Client.java new file mode 100644 index 00000000000..b896d9becc3 --- /dev/null +++ b/idea/testData/findUsages/findPropertyUsages/javaUsages/Client.java @@ -0,0 +1,9 @@ +package client; + +import server.O + +class Client { + fun fooBar() { + println("foo = " + O.instance$.getFoo()) + } +} \ No newline at end of file diff --git a/idea/testData/findUsages/findPropertyUsages/javaUsages/Server.kt b/idea/testData/findUsages/findPropertyUsages/javaUsages/Server.kt new file mode 100644 index 00000000000..388e800f3d2 --- /dev/null +++ b/idea/testData/findUsages/findPropertyUsages/javaUsages/Server.kt @@ -0,0 +1,6 @@ +package server; + +object O { + var foo: String = "foo" +} + diff --git a/idea/testData/findUsages/findPropertyUsages/kotlinUsages/Client.kt b/idea/testData/findUsages/findPropertyUsages/kotlinUsages/Client.kt new file mode 100644 index 00000000000..4d9a435b595 --- /dev/null +++ b/idea/testData/findUsages/findPropertyUsages/kotlinUsages/Client.kt @@ -0,0 +1,10 @@ +package client + +import server.foo + +class Client { + fun fooBar() { + println("foo = ${server.foo}") + println("length: ${server.foo.length()}") + } +} \ No newline at end of file diff --git a/idea/testData/findUsages/findPropertyUsages/kotlinUsages/Server.kt b/idea/testData/findUsages/findPropertyUsages/kotlinUsages/Server.kt new file mode 100644 index 00000000000..179159c259c --- /dev/null +++ b/idea/testData/findUsages/findPropertyUsages/kotlinUsages/Server.kt @@ -0,0 +1,4 @@ +package server; + +var foo: String = "foo" + diff --git a/idea/testData/safeDelete/deleteClass/class1.kt b/idea/testData/safeDelete/deleteClass/class1.kt new file mode 100644 index 00000000000..e9b460bc80e --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/class1.kt @@ -0,0 +1,11 @@ +package test + +import test.A + +class A { + +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/class1.kt.after b/idea/testData/safeDelete/deleteClass/class1.kt.after new file mode 100644 index 00000000000..191deddb2f8 --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/class1.kt.after @@ -0,0 +1,5 @@ +package test + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/class2.kt b/idea/testData/safeDelete/deleteClass/class2.kt new file mode 100644 index 00000000000..a2cc01c4685 --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/class2.kt @@ -0,0 +1,11 @@ +package test + +import test.A + +class A { + +} + +class B: A { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/class2.kt.messages b/idea/testData/safeDelete/deleteClass/class2.kt.messages new file mode 100644 index 00000000000..3b47612540c --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/class2.kt.messages @@ -0,0 +1,2 @@ +Class A has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/nestedClass1.kt b/idea/testData/safeDelete/deleteClass/nestedClass1.kt new file mode 100644 index 00000000000..eda9980f59b --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/nestedClass1.kt @@ -0,0 +1,13 @@ +package test + +import test.A.C + +class A { + class C { + + } +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/nestedClass1.kt.after b/idea/testData/safeDelete/deleteClass/nestedClass1.kt.after new file mode 100644 index 00000000000..31084708c8c --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/nestedClass1.kt.after @@ -0,0 +1,8 @@ +package test + +class A { +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/nestedClass2.kt b/idea/testData/safeDelete/deleteClass/nestedClass2.kt new file mode 100644 index 00000000000..88f09bcdf0a --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/nestedClass2.kt @@ -0,0 +1,13 @@ +package test + +import test.A.C + +class A { + class C { + + } +} + +class B { + val x = A.C() +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/nestedClass2.kt.messages b/idea/testData/safeDelete/deleteClass/nestedClass2.kt.messages new file mode 100644 index 00000000000..de7b986cf61 --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/nestedClass2.kt.messages @@ -0,0 +1,2 @@ +Class C has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/noUsages.kt b/idea/testData/safeDelete/deleteClass/noUsages.kt new file mode 100644 index 00000000000..7831382b7c4 --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/noUsages.kt @@ -0,0 +1,11 @@ +class C { + +} + +class A { + +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/noUsages.kt.after b/idea/testData/safeDelete/deleteClass/noUsages.kt.after new file mode 100644 index 00000000000..2bb2a83ef25 --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/noUsages.kt.after @@ -0,0 +1,7 @@ +class C { + +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/trait1.kt b/idea/testData/safeDelete/deleteClass/trait1.kt new file mode 100644 index 00000000000..db5643b508b --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/trait1.kt @@ -0,0 +1,10 @@ +package test + +import test.A + +trait A { +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/trait1.kt.after b/idea/testData/safeDelete/deleteClass/trait1.kt.after new file mode 100644 index 00000000000..191deddb2f8 --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/trait1.kt.after @@ -0,0 +1,5 @@ +package test + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/trait2.kt b/idea/testData/safeDelete/deleteClass/trait2.kt new file mode 100644 index 00000000000..61c2c37148b --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/trait2.kt @@ -0,0 +1,11 @@ +package test + +import test.A + +trait A { + +} + +class B: A { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/trait2.kt.messages b/idea/testData/safeDelete/deleteClass/trait2.kt.messages new file mode 100644 index 00000000000..599dc5b1810 --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/trait2.kt.messages @@ -0,0 +1,2 @@ +Trait A has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/unsafeImport.kt b/idea/testData/safeDelete/deleteClass/unsafeImport.kt new file mode 100644 index 00000000000..b208ab6468a --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/unsafeImport.kt @@ -0,0 +1,13 @@ +package test + +import test.A.C + +class A { + class C { + + } +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteClass/unsafeImport.kt.messages b/idea/testData/safeDelete/deleteClass/unsafeImport.kt.messages new file mode 100644 index 00000000000..3b47612540c --- /dev/null +++ b/idea/testData/safeDelete/deleteClass/unsafeImport.kt.messages @@ -0,0 +1,2 @@ +Class A has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/fun1.kt b/idea/testData/safeDelete/deleteFunction/fun1.kt new file mode 100644 index 00000000000..bd48ff9ec5a --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/fun1.kt @@ -0,0 +1,11 @@ +package test + +import test.foo + +fun foo() { + +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/fun1.kt.after b/idea/testData/safeDelete/deleteFunction/fun1.kt.after new file mode 100644 index 00000000000..191deddb2f8 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/fun1.kt.after @@ -0,0 +1,5 @@ +package test + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/fun2.kt b/idea/testData/safeDelete/deleteFunction/fun2.kt new file mode 100644 index 00000000000..8bd92224aa2 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/fun2.kt @@ -0,0 +1,11 @@ +package test + +import test.foo + +fun foo() { + +} + +class B { + val ref = ::foo +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/fun2.kt.messages b/idea/testData/safeDelete/deleteFunction/fun2.kt.messages new file mode 100644 index 00000000000..7d36bd30109 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/fun2.kt.messages @@ -0,0 +1,2 @@ +Function foo has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/implement1.kt b/idea/testData/safeDelete/deleteFunction/implement1.kt new file mode 100644 index 00000000000..d682b537116 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/implement1.kt @@ -0,0 +1,9 @@ +trait A { + fun foo() +} + +class B: A { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/implement1.kt.messages b/idea/testData/safeDelete/deleteFunction/implement1.kt.messages new file mode 100644 index 00000000000..faf8f3ae2c0 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/implement1.kt.messages @@ -0,0 +1 @@ +fun foo(): jet.Unit in final class B : A implements fun foo(): jet.Unit in trait A. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/implement2.kt b/idea/testData/safeDelete/deleteFunction/implement2.kt new file mode 100644 index 00000000000..d45ab2c6785 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/implement2.kt @@ -0,0 +1,13 @@ +trait A { + fun foo() +} + +trait Z { + fun foo() +} + +class B: A, Z { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/implement2.kt.messages b/idea/testData/safeDelete/deleteFunction/implement2.kt.messages new file mode 100644 index 00000000000..f1e89f82803 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/implement2.kt.messages @@ -0,0 +1,2 @@ +fun foo(): jet.Unit in final class B : A, Z implements fun foo(): jet.Unit in trait A. +fun foo(): jet.Unit in final class B : A, Z implements fun foo(): jet.Unit in trait Z. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/noUsages.kt b/idea/testData/safeDelete/deleteFunction/noUsages.kt new file mode 100644 index 00000000000..b05a392db1d --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/noUsages.kt @@ -0,0 +1,7 @@ +class C { + fun foo { + } +} + +class B { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/noUsages.kt.after b/idea/testData/safeDelete/deleteFunction/noUsages.kt.after new file mode 100644 index 00000000000..3f11a5b1fd3 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/noUsages.kt.after @@ -0,0 +1,5 @@ +class C { +} + +class B { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/override1.kt b/idea/testData/safeDelete/deleteFunction/override1.kt new file mode 100644 index 00000000000..73f238168cb --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/override1.kt @@ -0,0 +1,11 @@ +open class A { + open fun foo() { + + } +} + +class B: A { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/override1.kt.after b/idea/testData/safeDelete/deleteFunction/override1.kt.after new file mode 100644 index 00000000000..15c2912677e --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/override1.kt.after @@ -0,0 +1,8 @@ +open class A { + open fun foo() { + + } +} + +class B: A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/override2.kt b/idea/testData/safeDelete/deleteFunction/override2.kt new file mode 100644 index 00000000000..afdf4b91e97 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/override2.kt @@ -0,0 +1,11 @@ +open class A { + open fun foo() { + + } +} + +class B: A { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/override2.kt.after b/idea/testData/safeDelete/deleteFunction/override2.kt.after new file mode 100644 index 00000000000..4d87308c243 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/override2.kt.after @@ -0,0 +1,5 @@ +open class A { +} + +class B: A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/overrideAndImplement1.kt b/idea/testData/safeDelete/deleteFunction/overrideAndImplement1.kt new file mode 100644 index 00000000000..b11689d9a37 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/overrideAndImplement1.kt @@ -0,0 +1,15 @@ +open class A { + open fun foo() { + + } +} + +trait Z { + fun foo() +} + +class B: A, Z { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/overrideAndImplement1.kt.messages b/idea/testData/safeDelete/deleteFunction/overrideAndImplement1.kt.messages new file mode 100644 index 00000000000..b1f9c85864b --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/overrideAndImplement1.kt.messages @@ -0,0 +1 @@ +fun foo(): jet.Unit in final class B : A, Z implements fun foo(): jet.Unit in trait Z. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/overrideAndImplement2.kt b/idea/testData/safeDelete/deleteFunction/overrideAndImplement2.kt new file mode 100644 index 00000000000..053782794d8 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/overrideAndImplement2.kt @@ -0,0 +1,15 @@ +open class A { + open fun foo() { + + } +} + +trait Z { + fun foo() +} + +class B: A, Z { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/overrideAndImplement2.kt.after b/idea/testData/safeDelete/deleteFunction/overrideAndImplement2.kt.after new file mode 100644 index 00000000000..92575432fe6 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/overrideAndImplement2.kt.after @@ -0,0 +1,12 @@ +open class A { +} + +trait Z { + fun foo() +} + +class B: A, Z { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/overrideWithUsages.kt b/idea/testData/safeDelete/deleteFunction/overrideWithUsages.kt new file mode 100644 index 00000000000..50de3d0bfdb --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/overrideWithUsages.kt @@ -0,0 +1,15 @@ +open class A { + open fun foo() { + + } +} + +class B: A { + fun bar() { + foo() + } + + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunction/overrideWithUsages.kt.after b/idea/testData/safeDelete/deleteFunction/overrideWithUsages.kt.after new file mode 100644 index 00000000000..7d6de4fbd2f --- /dev/null +++ b/idea/testData/safeDelete/deleteFunction/overrideWithUsages.kt.after @@ -0,0 +1,12 @@ +open class A { +} + +class B: A { + fun bar() { + foo() + } + + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.java new file mode 100644 index 00000000000..9d1504fe3b6 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.java @@ -0,0 +1,3 @@ +interface A { + void foo(); +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.kt new file mode 100644 index 00000000000..a76fc973489 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.kt @@ -0,0 +1,5 @@ +class B: A { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.kt.messages b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.kt.messages new file mode 100644 index 00000000000..370cf8c5f42 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.kt.messages @@ -0,0 +1 @@ +fun foo(): jet.Unit in final class B : A implements [Java] void foo() in interface A. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.java new file mode 100644 index 00000000000..922ff12cbb2 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.java @@ -0,0 +1,5 @@ +class B implements A { + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.java.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.java.after new file mode 100644 index 00000000000..96506701c7c --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.java.after @@ -0,0 +1,2 @@ +class B implements A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.kt new file mode 100644 index 00000000000..f3a5a12bc65 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.kt @@ -0,0 +1,3 @@ +trait A { + fun foo() +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.kt.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.kt.after new file mode 100644 index 00000000000..670cabdb241 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.kt.after @@ -0,0 +1,2 @@ +trait A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.java new file mode 100644 index 00000000000..f39830b8fc1 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.java @@ -0,0 +1,7 @@ +interface A { + void foo(); +} + +interface Z { + void foo(); +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.kt new file mode 100644 index 00000000000..c6b6e0d3ee9 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.kt @@ -0,0 +1,5 @@ +class B: A, Z { + public override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.kt.messages b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.kt.messages new file mode 100644 index 00000000000..f6a48a49969 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.kt.messages @@ -0,0 +1,2 @@ +fun foo(): jet.Unit in final class B : A, Z implements [Java] void foo() in interface A. +fun foo(): jet.Unit in final class B : A, Z implements [Java] void foo() in interface Z. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.java new file mode 100644 index 00000000000..f8cba162620 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.java @@ -0,0 +1,5 @@ +class B implements A, Z { + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.java.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.java.after new file mode 100644 index 00000000000..f8cba162620 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.java.after @@ -0,0 +1,5 @@ +class B implements A, Z { + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.kt new file mode 100644 index 00000000000..3470b144414 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.kt @@ -0,0 +1,7 @@ +trait A { + fun foo() +} + +trait Z { + fun foo() +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.kt.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.kt.after new file mode 100644 index 00000000000..4b0d260090e --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.kt.after @@ -0,0 +1,6 @@ +trait A { +} + +trait Z { + fun foo() +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.java new file mode 100644 index 00000000000..59ea3d006c7 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.java @@ -0,0 +1,5 @@ +class A { + void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.java.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.java.after new file mode 100644 index 00000000000..59ea3d006c7 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.java.after @@ -0,0 +1,5 @@ +class A { + void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.kt new file mode 100644 index 00000000000..a76fc973489 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.kt @@ -0,0 +1,5 @@ +class B: A { + override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.kt.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.kt.after new file mode 100644 index 00000000000..994dc58cf69 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.kt.after @@ -0,0 +1,2 @@ +class B: A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.java new file mode 100644 index 00000000000..315ae36bf5a --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.java @@ -0,0 +1,6 @@ +class B extends A { + @Override + void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.java.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.java.after new file mode 100644 index 00000000000..99b93165680 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.java.after @@ -0,0 +1,2 @@ +class B extends A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.kt new file mode 100644 index 00000000000..f3d6421d400 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.kt @@ -0,0 +1,5 @@ +open class A { + open fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.kt.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.kt.after new file mode 100644 index 00000000000..d80ee90d357 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.kt.after @@ -0,0 +1,2 @@ +open class A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.java new file mode 100644 index 00000000000..6647e4afa78 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.java @@ -0,0 +1,10 @@ +class B extends A { + void bar() { + foo(); + } + + @Override + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.java.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.java.after new file mode 100644 index 00000000000..774a6b0c204 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.java.after @@ -0,0 +1,9 @@ +class B extends A { + void bar() { + foo(); + } + + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.kt new file mode 100644 index 00000000000..f3d6421d400 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.kt @@ -0,0 +1,5 @@ +open class A { + open fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.kt.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.kt.after new file mode 100644 index 00000000000..d80ee90d357 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.kt.after @@ -0,0 +1,2 @@ +open class A { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.java new file mode 100644 index 00000000000..780d713081d --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.java @@ -0,0 +1,9 @@ +class A { + public void foo() { + + } +} + +interface Z { + void foo(); +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.kt new file mode 100644 index 00000000000..c6b6e0d3ee9 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.kt @@ -0,0 +1,5 @@ +class B: A, Z { + public override fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.kt.messages b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.kt.messages new file mode 100644 index 00000000000..1f17b7e2ff5 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.kt.messages @@ -0,0 +1 @@ +fun foo(): jet.Unit in final class B : A, Z implements [Java] void foo() in interface Z. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.java b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.java new file mode 100644 index 00000000000..8e3a7341f25 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.java @@ -0,0 +1,5 @@ +class B extends A implements Z { + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.java.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.java.after new file mode 100644 index 00000000000..8e3a7341f25 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.java.after @@ -0,0 +1,5 @@ +class B extends A implements Z { + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.kt b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.kt new file mode 100644 index 00000000000..46b50ab2ac9 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.kt @@ -0,0 +1,9 @@ +class A { + public fun foo() { + + } +} + +trait Z { + fun foo() +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.kt.after b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.kt.after new file mode 100644 index 00000000000..ce7ab3cebd7 --- /dev/null +++ b/idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.kt.after @@ -0,0 +1,6 @@ +class A { +} + +trait Z { + fun foo() +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.java b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.java new file mode 100644 index 00000000000..7ee62ca2e46 --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.java @@ -0,0 +1,10 @@ +interface A { + public void foo(); +} + +abstract class C implements B { + @Override + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.java.after b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.java.after new file mode 100644 index 00000000000..e91065bc7be --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.java.after @@ -0,0 +1,5 @@ +interface A { +} + +abstract class C implements B { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.kt b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.kt new file mode 100644 index 00000000000..4bde1062335 --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.kt @@ -0,0 +1,11 @@ +trait B: A { + public override fun foo() { + throw UnsupportedOperationException() + } +} + +class D: C() { + public override fun foo() { + throw UnsupportedOperationException() + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.kt.after b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.kt.after new file mode 100644 index 00000000000..d1fffa7e4b8 --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.kt.after @@ -0,0 +1,5 @@ +trait B: A { +} + +class D: C() { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.java b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.java new file mode 100644 index 00000000000..88d0495e439 --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.java @@ -0,0 +1,10 @@ +interface A { + public void foo(); +} + +abstract class C implements B { + @Override + public void foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.java.after b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.java.after new file mode 100644 index 00000000000..525267c9118 --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.java.after @@ -0,0 +1,6 @@ +interface A { + public void foo(); +} + +abstract class C implements B { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.kt b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.kt new file mode 100644 index 00000000000..4bde1062335 --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.kt @@ -0,0 +1,11 @@ +trait B: A { + public override fun foo() { + throw UnsupportedOperationException() + } +} + +class D: C() { + public override fun foo() { + throw UnsupportedOperationException() + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.kt.after b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.kt.after new file mode 100644 index 00000000000..d208f64b7a7 --- /dev/null +++ b/idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.kt.after @@ -0,0 +1,8 @@ +trait B: A { + public override fun foo() { + throw UnsupportedOperationException() + } +} + +class D: C() { +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/nestedObject1.kt b/idea/testData/safeDelete/deleteObject/nestedObject1.kt new file mode 100644 index 00000000000..163a596ca56 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/nestedObject1.kt @@ -0,0 +1,11 @@ +package test + +object A { + object O { + + } +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/nestedObject1.kt.after b/idea/testData/safeDelete/deleteObject/nestedObject1.kt.after new file mode 100644 index 00000000000..af2dd5b418f --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/nestedObject1.kt.after @@ -0,0 +1,8 @@ +package test + +object A { +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/nestedObject2.kt b/idea/testData/safeDelete/deleteObject/nestedObject2.kt new file mode 100644 index 00000000000..259ccd0b136 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/nestedObject2.kt @@ -0,0 +1,13 @@ +package test + +import test.A.O + +object A { + object O { + + } +} + +class B { + val x = A.O +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/nestedObject2.kt.messages b/idea/testData/safeDelete/deleteObject/nestedObject2.kt.messages new file mode 100644 index 00000000000..aed29791f35 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/nestedObject2.kt.messages @@ -0,0 +1,2 @@ +Object O has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/noUsages.kt b/idea/testData/safeDelete/deleteObject/noUsages.kt new file mode 100644 index 00000000000..aa9f22bd145 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/noUsages.kt @@ -0,0 +1,11 @@ +class C { + +} + +object A { + +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/noUsages.kt.after b/idea/testData/safeDelete/deleteObject/noUsages.kt.after new file mode 100644 index 00000000000..2bb2a83ef25 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/noUsages.kt.after @@ -0,0 +1,7 @@ +class C { + +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/object1.kt b/idea/testData/safeDelete/deleteObject/object1.kt new file mode 100644 index 00000000000..819a8024eb1 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/object1.kt @@ -0,0 +1,11 @@ +package test + +import test.A + +object A { + +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/object1.kt.after b/idea/testData/safeDelete/deleteObject/object1.kt.after new file mode 100644 index 00000000000..191deddb2f8 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/object1.kt.after @@ -0,0 +1,5 @@ +package test + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/object2.kt b/idea/testData/safeDelete/deleteObject/object2.kt new file mode 100644 index 00000000000..33a73c4c538 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/object2.kt @@ -0,0 +1,11 @@ +package test + +import test.A + +object A { + +} + +class B { + val x = A +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/object2.kt.messages b/idea/testData/safeDelete/deleteObject/object2.kt.messages new file mode 100644 index 00000000000..464daffdd24 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/object2.kt.messages @@ -0,0 +1,2 @@ +Object A has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/unsafeImport.kt b/idea/testData/safeDelete/deleteObject/unsafeImport.kt new file mode 100644 index 00000000000..e2c5ea55eec --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/unsafeImport.kt @@ -0,0 +1,11 @@ +package test + +import test.A.x + +object A { + val x = "" +} + +class B { + +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteObject/unsafeImport.kt.messages b/idea/testData/safeDelete/deleteObject/unsafeImport.kt.messages new file mode 100644 index 00000000000..464daffdd24 --- /dev/null +++ b/idea/testData/safeDelete/deleteObject/unsafeImport.kt.messages @@ -0,0 +1,2 @@ +Object A has 1 usage that is not safe to delete. +Of those 0 usages are in strings, comments, or non-code files. \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTest.java b/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTest.java index 5473b55c665..33e8c702c07 100644 --- a/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTest.java +++ b/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTest.java @@ -22,18 +22,24 @@ import com.google.common.base.Predicates; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.usageView.UsageInfo; import com.intellij.usages.UsageInfo2UsageAdapter; +import com.intellij.usages.impl.rules.UsageType; +import com.intellij.usages.impl.rules.UsageTypeProvider; import com.intellij.usages.rules.UsageFilteringRule; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lang.psi.JetObjectDeclarationName; +import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.plugin.JetLightProjectDescriptor; import org.jetbrains.jet.plugin.PluginTestCaseBase; import org.jetbrains.jet.plugin.findUsages.JetImportFilteringRule; @@ -55,25 +61,119 @@ public class JetFindUsagesTest extends LightCodeInsightFixtureTestCase { myFixture.setTestDataPath(PluginTestCaseBase.getTestDataPathBase() + "/findUsages"); } - public void testFindClassUsages() { + public void testFindClassJavaUsages() { doTestWithoutFiltering( - Lists.newArrayList("findClassUsages/Server.kt", "findClassUsages/Client.java"), + Lists.newArrayList("findClassUsages/javaUsages/Server.kt", "findClassUsages/javaUsages/Client.java"), JetClass.class, - Lists.newArrayList("(4: 13) private Server myServer;")); + Lists.newArrayList("Field declaration (4: 13) private Server myServer;")); + } + + public void testFindClassKotlinUsages1() { + doTestWithoutFiltering( + Lists.newArrayList("findClassUsages/kotlinUsages1/Server.kt", "findClassUsages/kotlinUsages1/Client.kt"), + JetClass.class, + Lists.newArrayList( + "Class/object property type (6: 21) var nextServer: Server? = null", + "Function return types (14: 26) fun getNextServer(): Server? {", + "Function return types (32: 21) fun Any.asServer(): Server? {", + "Import directive (3: 15) import server.Server", + "Local variable type (10: 21) val server: Server = s", + "Nested class/object (7: 16) val name = Server.NAME", + "Parameter type (24: 19) fun Client.bar(s: Server) {", + "Parameter type (9: 16) fun foo(s: Server) {", + "Super type qualifier (19: 15) super.work()", + "Supertype (5: 15) class Client: Server {", + "Target type of 'as' operation (33: 40) return if (this is Server) this as Server else null", + "Target type of 'is' operation (33: 24) return if (this is Server) this as Server else null" + )); + } + + public void testFindClassKotlinUsages2() { + doTestWithoutFiltering( + Lists.newArrayList("findClassUsages/kotlinUsages2/Server.kt", "findClassUsages/kotlinUsages2/Client.kt"), + JetClass.class, + Lists.newArrayList( + "Annotation (5: 1) X(\"\")", + "Import directive (3: 15) import server.X" + )); + } + + public void testFindClassKotlinUsages3() { + doTestWithoutFiltering( + Lists.newArrayList("findClassUsages/kotlinUsages3/Server.kt", "findClassUsages/kotlinUsages3/Client.kt"), + JetClass.class, + Lists.newArrayList( + "Import directive (3: 15) import server.Data", + "Type argument (9: 16) val c = Client()", + "Type constraint (5: 17) class Client where X: Data {", + "Type constraint (5: 35) class Client where X: Data {" + )); } public void testFindUsagesUnresolvedAnnotation() { doTestWithoutFiltering( Lists.newArrayList("unresolvedAnnotation/Server.kt", "unresolvedAnnotation/Client.java"), JetClass.class, - Lists.newArrayList("(1: 29) public class Client extends Foo {}")); + Lists.newArrayList("Usage in extends/implements clause (1: 29) public class Client extends Foo {}")); } - public void testFindMethodUsages() { + public void testFindMethodJavaUsages() { doTestWithoutFiltering( - Lists.newArrayList("findMethodUsages/Server.kt", "findMethodUsages/Client.java"), + Lists.newArrayList("findMethodUsages/javaUsages/Server.kt", "findMethodUsages/javaUsages/Client.java"), JetFunction.class, - Lists.newArrayList("(6: 16) server.processRequest();")); + Lists.newArrayList("Unclassified usage (6: 16) server.processRequest();")); + } + + public void testFindMethodKotlinUsages() { + doTestWithoutFiltering( + Lists.newArrayList("findMethodUsages/kotlinUsages/Server.kt", "findMethodUsages/kotlinUsages/Client.kt"), + JetFunction.class, + Lists.newArrayList( + "Callable reference (6: 23) val methodRef = ::processRequest()", + "Function call (10: 9) processRequest()", + "Import directive (3: 15) import server.processRequest" + )); + } + + public void testFindPropertyJavaUsages() { + doTestWithoutFiltering( + Lists.newArrayList("findPropertyUsages/javaUsages/Server.kt", "findPropertyUsages/javaUsages/Client.java"), + JetProperty.class, + Lists.newArrayList( + "Unclassified usage (7: 40) println(\"foo = \" + O.instance$.getFoo())" + )); + } + + public void testFindPropertyKotlinUsages() { + doTestWithoutFiltering( + Lists.newArrayList("findPropertyUsages/kotlinUsages/Server.kt", "findPropertyUsages/kotlinUsages/Client.kt"), + JetProperty.class, + Lists.newArrayList( + "Import directive (3: 15) import server.foo", + "Receiver (8: 35) println(\"length: ${server.foo.length()}\")", + "Selector (7: 33) println(\"foo = ${server.foo}\")" + )); + } + + public void testFindObjectJavaUsages() { + doTestWithoutFiltering( + Lists.newArrayList("findObjectUsages/javaUsages/Server.kt", "findObjectUsages/javaUsages/Client.java"), + JetObjectDeclarationName.class, + Lists.newArrayList( + "Class static member access (7: 28) println(\"foo = \" + O.instance$.getFoo())", + "Usage in import (3: 15) import server.O" + )); + } + + public void testFindObjectKotlinUsages() { + doTestWithoutFiltering( + Lists.newArrayList("findObjectUsages/kotlinUsages/Server.kt", "findObjectUsages/kotlinUsages/Client.kt"), + JetObjectDeclarationName.class, + Lists.newArrayList( + "Import directive (3: 15) import server.O", + "Receiver (7: 26) println(\"foo = ${O.foo}\")", + "Value read (8: 19) val obj = O" + )); } public void testFindWithFilteringImports() { @@ -81,18 +181,22 @@ public class JetFindUsagesTest extends LightCodeInsightFixtureTestCase { JetClass.class, 2, Lists.newArrayList(new JetImportFilteringRule()), - Lists.newArrayList("(5: 9) val a = Test()")); + Lists.newArrayList("Instantiation (5: 9) val a = Test()")); } - private void doTestWithoutFiltering(Collection files, Class caretElementClass, Collection expectedUsages) { + private void doTestWithoutFiltering( + Collection files, + Class caretElementClass, + Collection expectedUsages + ) { doTest(files, caretElementClass, expectedUsages.size(), Collections.emptyList(), expectedUsages); } - private void doTest( + private void doTest( Collection files, Class caretElementClass, int numberOfNotFilteredUsages, - final Collection filters, + Collection filters, Collection expectedUsages ) { myFixture.configureByFiles(ArrayUtil.toObjectArray(files, String.class)); @@ -103,34 +207,60 @@ public class JetFindUsagesTest extends LightCodeInsightFixtureTestCase { assertEquals(numberOfNotFilteredUsages, usageInfos.size()); - Collection filteredUsages = - Collections2.filter( - Collections2.transform(usageInfos, new Function() { - @Override - public UsageInfo2UsageAdapter apply(@Nullable UsageInfo usageInfo) { - assert (usageInfo != null); - - UsageInfo2UsageAdapter usageAdapter = new UsageInfo2UsageAdapter(usageInfo); - for (UsageFilteringRule filter : filters) { - if (!filter.isVisible(usageAdapter)) { - return null; - } - } - - return usageAdapter; - } - }), - Predicates.notNull()); + Collection filteredUsages = getUsageAdapters(filters, usageInfos); Function convertToString = new Function() { @Override public String apply(@Nullable UsageInfo2UsageAdapter usageAdapter) { assert usageAdapter != null; - return Joiner.on("").join(Arrays.asList(usageAdapter.getPresentation().getText())); + return getUsageType(usageAdapter.getElement()) + + " " + Joiner.on("").join(Arrays.asList(usageAdapter.getPresentation().getText())); } }; Collection finalUsages = Ordering.natural().sortedCopy(Collections2.transform(filteredUsages, convertToString)); assertOrderedEquals(finalUsages, Ordering.natural().sortedCopy(expectedUsages)); } + + private static Collection getUsageAdapters( + final Collection filters, + Collection usageInfos + ) { + return Collections2.filter( + Collections2.transform(usageInfos, new Function() { + @Override + public UsageInfo2UsageAdapter apply(@Nullable UsageInfo usageInfo) { + assert (usageInfo != null); + + UsageInfo2UsageAdapter usageAdapter = new UsageInfo2UsageAdapter(usageInfo); + for (UsageFilteringRule filter : filters) { + if (!filter.isVisible(usageAdapter)) { + return null; + } + } + + return usageAdapter; + } + }), + Predicates.notNull()); + } + + @Nullable + private static UsageType getUsageType(PsiElement element) { + if (element == null) return null; + + if (PsiTreeUtil.getParentOfType(element, PsiComment.class, false) != null) { + return UsageType.COMMENT_USAGE; + } + + UsageTypeProvider[] providers = Extensions.getExtensions(UsageTypeProvider.EP_NAME); + for (UsageTypeProvider provider : providers) { + UsageType usageType = provider.getUsageType(element); + if (usageType != null) { + return usageType; + } + } + + return UsageType.UNCLASSIFIED; + } } diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java index 7666e80dbd4..3864131f9e6 100644 --- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java @@ -817,6 +817,16 @@ public class CodeMoverTestGenerated extends AbstractCodeMoverTest { doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt"); } + @TestMetadata("closureWthoutSpaces1.kt") + public void testClosureWthoutSpaces1() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces1.kt"); + } + + @TestMetadata("closureWthoutSpaces2.kt") + public void testClosureWthoutSpaces2() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureWthoutSpaces2.kt"); + } + @TestMetadata("declaration1.kt") public void testDeclaration1() throws Exception { doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/declaration1.kt"); diff --git a/idea/tests/org/jetbrains/jet/safeDelete/AbstractJetSafeDeleteTest.java b/idea/tests/org/jetbrains/jet/safeDelete/AbstractJetSafeDeleteTest.java new file mode 100644 index 00000000000..0ef86248851 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/safeDelete/AbstractJetSafeDeleteTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.safeDelete; + +import com.intellij.codeInsight.TargetElementUtilBase; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.refactoring.safeDelete.SafeDeleteHandler; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.psi.JetObjectDeclarationName; +import org.jetbrains.jet.plugin.JetLightProjectDescriptor; +import org.jetbrains.jet.plugin.PluginTestCaseBase; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public abstract class AbstractJetSafeDeleteTest extends LightCodeInsightFixtureTestCase { + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JetLightProjectDescriptor.INSTANCE; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + String pathBase = PluginTestCaseBase.getTestDataPathBase(); + myFixture.setTestDataPath(pathBase.substring(0, pathBase.lastIndexOf("/idea/testData"))); + } + + public void doClassTest(@NotNull String path) throws Exception { + doTest(path, JetClass.class, false); + } + + public void doObjectTest(@NotNull String path) throws Exception { + doTest(path, JetObjectDeclarationName.class, false); + } + + public void doFunctionTest(@NotNull String path) throws Exception { + doTest(path, JetNamedFunction.class, false); + } + + public void doFunctionTestWithJava(@NotNull String path) throws Exception { + doTest(path, JetNamedFunction.class, true); + } + + public void doJavaMethodTest(@NotNull String path) throws Exception { + doTest(path, PsiMethod.class, true); + } + + private void doTest( + @NotNull String path, @NotNull Class elementClass, boolean withJava) throws Exception { + String[] filePaths; + if (withJava) { + filePaths = new String[]{path, path.endsWith(".java") ? path.replace(".java", ".kt") : path.replace(".kt", ".java")}; + } + else { + filePaths = new String[]{path}; + } + + Editor[] editors = new Editor[filePaths.length]; + int i = 0; + for (String filePath : filePaths) { + myFixture.configureByFile(filePath); + editors[i++] = myFixture.getEditor(); + } + + PsiElement elementAtCaret = null; + for (Editor editor : editors) { + elementAtCaret = TargetElementUtilBase.findTargetElement( + editor, TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED | TargetElementUtilBase.ELEMENT_NAME_ACCEPTED + ); + if (elementAtCaret != null) break; + } + + assertNotNull("Couldn't find element at caret position", elementAtCaret); + + T element = PsiTreeUtil.getParentOfType(elementAtCaret, elementClass, false); + + try { + SafeDeleteHandler.invoke(getProject(), new PsiElement[] {element}, null, true, null); + for (int j = 0; j < filePaths.length; j++) { + String expectedText = FileUtil.loadFile(new File(filePaths[j] + ".after")); + assertEquals(StringUtil.convertLineSeparators(expectedText), editors[j].getDocument().getText()); + } + } + catch (BaseRefactoringProcessor.ConflictsInTestsException e) { + List messages = new ArrayList(e.getMessages()); + Collections.sort(messages); + + File messageFile = new File(path + ".messages"); + String expectedMessage = FileUtil.loadFile(messageFile, CharsetToolkit.UTF8, true); + assertEquals(expectedMessage, StringUtil.join(messages, "\n")); + } + } +} diff --git a/idea/tests/org/jetbrains/jet/safeDelete/JetSafeDeleteTestGenerated.java b/idea/tests/org/jetbrains/jet/safeDelete/JetSafeDeleteTestGenerated.java new file mode 100644 index 00000000000..78d2ffdb3e1 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/safeDelete/JetSafeDeleteTestGenerated.java @@ -0,0 +1,259 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.safeDelete; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestSuite; + +import java.io.File; +import java.util.regex.Pattern; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; + +import org.jetbrains.jet.safeDelete.AbstractJetSafeDeleteTest; + +/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@InnerTestClasses({JetSafeDeleteTestGenerated.DeleteClass.class, JetSafeDeleteTestGenerated.DeleteObject.class, JetSafeDeleteTestGenerated.DeleteFunction.class, JetSafeDeleteTestGenerated.DeleteFunctionWithJavaUsages.class, JetSafeDeleteTestGenerated.DeleteJavaMethod.class}) +public class JetSafeDeleteTestGenerated extends AbstractJetSafeDeleteTest { + @TestMetadata("idea/testData/safeDelete/deleteClass") + public static class DeleteClass extends AbstractJetSafeDeleteTest { + public void testAllFilesPresentInDeleteClass() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/safeDelete/deleteClass"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("class1.kt") + public void testClass1() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/class1.kt"); + } + + @TestMetadata("class2.kt") + public void testClass2() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/class2.kt"); + } + + @TestMetadata("nestedClass1.kt") + public void testNestedClass1() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/nestedClass1.kt"); + } + + @TestMetadata("nestedClass2.kt") + public void testNestedClass2() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/nestedClass2.kt"); + } + + @TestMetadata("noUsages.kt") + public void testNoUsages() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/noUsages.kt"); + } + + @TestMetadata("trait1.kt") + public void testTrait1() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/trait1.kt"); + } + + @TestMetadata("trait2.kt") + public void testTrait2() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/trait2.kt"); + } + + @TestMetadata("unsafeImport.kt") + public void testUnsafeImport() throws Exception { + doClassTest("idea/testData/safeDelete/deleteClass/unsafeImport.kt"); + } + + } + + @TestMetadata("idea/testData/safeDelete/deleteObject") + public static class DeleteObject extends AbstractJetSafeDeleteTest { + public void testAllFilesPresentInDeleteObject() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/safeDelete/deleteObject"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("nestedObject1.kt") + public void testNestedObject1() throws Exception { + doObjectTest("idea/testData/safeDelete/deleteObject/nestedObject1.kt"); + } + + @TestMetadata("nestedObject2.kt") + public void testNestedObject2() throws Exception { + doObjectTest("idea/testData/safeDelete/deleteObject/nestedObject2.kt"); + } + + @TestMetadata("noUsages.kt") + public void testNoUsages() throws Exception { + doObjectTest("idea/testData/safeDelete/deleteObject/noUsages.kt"); + } + + @TestMetadata("object1.kt") + public void testObject1() throws Exception { + doObjectTest("idea/testData/safeDelete/deleteObject/object1.kt"); + } + + @TestMetadata("object2.kt") + public void testObject2() throws Exception { + doObjectTest("idea/testData/safeDelete/deleteObject/object2.kt"); + } + + @TestMetadata("unsafeImport.kt") + public void testUnsafeImport() throws Exception { + doObjectTest("idea/testData/safeDelete/deleteObject/unsafeImport.kt"); + } + + } + + @TestMetadata("idea/testData/safeDelete/deleteFunction") + public static class DeleteFunction extends AbstractJetSafeDeleteTest { + public void testAllFilesPresentInDeleteFunction() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/safeDelete/deleteFunction"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("fun1.kt") + public void testFun1() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/fun1.kt"); + } + + @TestMetadata("fun2.kt") + public void testFun2() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/fun2.kt"); + } + + @TestMetadata("implement1.kt") + public void testImplement1() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/implement1.kt"); + } + + @TestMetadata("implement2.kt") + public void testImplement2() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/implement2.kt"); + } + + @TestMetadata("noUsages.kt") + public void testNoUsages() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/noUsages.kt"); + } + + @TestMetadata("override1.kt") + public void testOverride1() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/override1.kt"); + } + + @TestMetadata("override2.kt") + public void testOverride2() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/override2.kt"); + } + + @TestMetadata("overrideAndImplement1.kt") + public void testOverrideAndImplement1() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/overrideAndImplement1.kt"); + } + + @TestMetadata("overrideAndImplement2.kt") + public void testOverrideAndImplement2() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/overrideAndImplement2.kt"); + } + + @TestMetadata("overrideWithUsages.kt") + public void testOverrideWithUsages() throws Exception { + doFunctionTest("idea/testData/safeDelete/deleteFunction/overrideWithUsages.kt"); + } + + } + + @TestMetadata("idea/testData/safeDelete/deleteFunctionWithJavaUsages") + public static class DeleteFunctionWithJavaUsages extends AbstractJetSafeDeleteTest { + public void testAllFilesPresentInDeleteFunctionWithJavaUsages() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/safeDelete/deleteFunctionWithJavaUsages"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("implement1.kt") + public void testImplement1() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement1.kt"); + } + + @TestMetadata("implement2.kt") + public void testImplement2() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement2.kt"); + } + + @TestMetadata("implement3.kt") + public void testImplement3() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement3.kt"); + } + + @TestMetadata("implement4.kt") + public void testImplement4() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/implement4.kt"); + } + + @TestMetadata("override1.kt") + public void testOverride1() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/override1.kt"); + } + + @TestMetadata("override2.kt") + public void testOverride2() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/override2.kt"); + } + + @TestMetadata("override3.kt") + public void testOverride3() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/override3.kt"); + } + + @TestMetadata("overrideAndImplement1.kt") + public void testOverrideAndImplement1() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement1.kt"); + } + + @TestMetadata("overrideAndImplement2.kt") + public void testOverrideAndImplement2() throws Exception { + doFunctionTestWithJava("idea/testData/safeDelete/deleteFunctionWithJavaUsages/overrideAndImplement2.kt"); + } + + } + + @TestMetadata("idea/testData/safeDelete/deleteJavaMethod") + public static class DeleteJavaMethod extends AbstractJetSafeDeleteTest { + public void testAllFilesPresentInDeleteJavaMethod() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/safeDelete/deleteJavaMethod"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("mixedHierarchy1.kt") + public void testMixedHierarchy1() throws Exception { + doJavaMethodTest("idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy1.kt"); + } + + @TestMetadata("mixedHierarchy2.kt") + public void testMixedHierarchy2() throws Exception { + doJavaMethodTest("idea/testData/safeDelete/deleteJavaMethod/mixedHierarchy2.kt"); + } + + } + + public static Test suite() { + TestSuite suite = new TestSuite("JetSafeDeleteTestGenerated"); + suite.addTestSuite(DeleteClass.class); + suite.addTestSuite(DeleteObject.class); + suite.addTestSuite(DeleteFunction.class); + suite.addTestSuite(DeleteFunctionWithJavaUsages.class); + suite.addTestSuite(DeleteJavaMethod.class); + return suite; + } +} diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/TraitTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/TraitTest.java index 6d130220da0..a317aa70042 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/TraitTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/TraitTest.java @@ -62,4 +62,8 @@ public final class TraitTest extends SingleFileTranslationTest { public void testDefinitionOrder() throws Exception { fooBoxTest(); } + + public void testCheckImplementationCharacteristics() throws Exception { + checkFooBoxIsOk(); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/AliasingContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/AliasingContext.java index 0d8456137df..667a19e24c0 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/AliasingContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/AliasingContext.java @@ -18,46 +18,18 @@ package org.jetbrains.k2js.translate.context; import com.google.common.collect.Maps; import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsLiteral; import com.google.dart.compiler.backend.js.ast.JsName; -import com.google.dart.compiler.backend.js.ast.JsNameRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.resolve.scopes.receivers.*; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver; -import java.util.Map; - -import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getDeclarationDescriptorForReceiver; -import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor; +import java.util.*; public class AliasingContext { - private static final ThisAliasProvider EMPTY_THIS_ALIAS_PROVIDER = new ThisAliasProvider() { - @Nullable + private static final AliasingContext ROOT = new AliasingContext(null) { @Override - public JsNameRef get(@NotNull DeclarationDescriptor descriptor) { - return null; - } - - @Nullable - @Override - public JsExpression get(@NotNull ResolvedCall call) { - ReceiverValue callThisObject = call.getThisObject(); - return callThisObject.exists() && (callThisObject instanceof ClassReceiver || callThisObject instanceof ExtensionReceiver) - ? JsLiteral.THIS - : null; - } - }; - - private static final AliasingContext ROOT = new AliasingContext(null, EMPTY_THIS_ALIAS_PROVIDER) { - @Override - public JsName getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) { + public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) { return null; } @@ -68,114 +40,76 @@ public class AliasingContext { }; public static AliasingContext getCleanContext() { - return new AliasingContext(ROOT, ROOT.thisAliasProvider); + return new AliasingContext(ROOT); } - @NotNull - private final Map aliasesForDescriptors = Maps.newHashMap(); + @Nullable + private Map aliasesForDescriptors; - @NotNull - final ThisAliasProvider thisAliasProvider; @NotNull private final Map aliasesForExpressions = Maps.newHashMap(); @Nullable private final AliasingContext parent; - private AliasingContext(@Nullable AliasingContext parent, @NotNull ThisAliasProvider thisAliasProvider) { + private AliasingContext(@Nullable AliasingContext parent) { + this(parent, null); + } + + private AliasingContext(@Nullable AliasingContext parent, @Nullable Map aliasesForDescriptors) { this.parent = parent; - this.thisAliasProvider = thisAliasProvider; - } - - public interface ThisAliasProvider { - @Nullable - JsNameRef get(@NotNull DeclarationDescriptor descriptor); - @Nullable - JsExpression get(@NotNull ResolvedCall call); - } - - public abstract static class AbstractThisAliasProvider implements ThisAliasProvider { - @NotNull - protected static DeclarationDescriptor normalize(@NotNull DeclarationDescriptor descriptor) { - if (descriptor instanceof ClassOrNamespaceDescriptor) { - return descriptor; - } - else if (descriptor instanceof CallableDescriptor) { - DeclarationDescriptor receiverDescriptor = getExpectedReceiverDescriptor((CallableDescriptor) descriptor); - assert receiverDescriptor != null; - return receiverDescriptor; - } - - return descriptor; - } - - @Nullable - @Override - public JsExpression get(@NotNull ResolvedCall call) { - ReceiverValue thisObject = call.getThisObject(); - if (!thisObject.exists()) { - return null; - } - - if (thisObject instanceof ExtensionReceiver || thisObject instanceof ClassReceiver) { - JsNameRef ref = get(((ThisReceiver) thisObject).getDeclarationDescriptor()); - if (ref != null) { - return ref; - } - } - - JsNameRef ref = get(getDeclarationDescriptorForReceiver(thisObject)); - return ref == null ? JsLiteral.THIS : ref; - } + this.aliasesForDescriptors = aliasesForDescriptors; } @NotNull - public AliasingContext inner(@NotNull ThisAliasProvider thisAliasProvider) { - return new AliasingContext(this, thisAliasProvider); - } - - @NotNull - public AliasingContext inner(@NotNull final DeclarationDescriptor correspondingDescriptor, @NotNull final JsName alias) { - return inner(new AbstractThisAliasProvider() { - @Nullable - @Override - public JsNameRef get(@NotNull DeclarationDescriptor descriptor) { - return correspondingDescriptor == normalize(descriptor) ? alias.makeRef() : null; - } - }); + public AliasingContext inner(@NotNull DeclarationDescriptor descriptor, @NotNull JsExpression alias) { + return new AliasingContext(this, Collections.singletonMap(descriptor, alias)); } @NotNull public AliasingContext withAliasesForExpressions(@NotNull Map aliasesForExpressions) { - AliasingContext newContext = new AliasingContext(this, thisAliasProvider); + AliasingContext newContext = new AliasingContext(this); newContext.aliasesForExpressions.putAll(aliasesForExpressions); return newContext; } @NotNull - public AliasingContext withDescriptorsAliased(@NotNull Map aliases) { - AliasingContext newContext = new AliasingContext(this, thisAliasProvider); - newContext.aliasesForDescriptors.putAll(aliases); - return newContext; + public AliasingContext withDescriptorsAliased(@NotNull Map aliases) { + return new AliasingContext(this, aliases); } @Nullable - public JsName getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) { - JsName alias = aliasesForDescriptors.get(descriptor.getOriginal()); + public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) { + if (aliasesForDescriptors == null) { + return null; + } + + JsExpression alias = aliasesForDescriptors.get(descriptor.getOriginal()); if (alias != null) { return alias; } - assert parent != null; + return parent.getAliasForDescriptor(descriptor); } @Nullable public JsName getAliasForExpression(@NotNull JetExpression element) { JsName alias = aliasesForExpressions.get(element); - if (alias != null) { - return alias; + return alias != null ? alias : parent.getAliasForExpression(element); + } + + public void registerAlias(@NotNull DeclarationDescriptor descriptor, @NotNull JsExpression alias) { + if (aliasesForDescriptors == null) { + aliasesForDescriptors = Collections.singletonMap(descriptor, alias); + } + else { + if (aliasesForDescriptors.size() == 1) { + Map singletonMap = aliasesForDescriptors; + aliasesForDescriptors = new HashMap(); + aliasesForDescriptors.put(singletonMap.keySet().iterator().next(), singletonMap.values().iterator().next()); + } + JsExpression prev = aliasesForDescriptors.put(descriptor, alias); + assert prev == null; } - assert parent != null; - return parent.getAliasForExpression(element); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/TraceableThisAliasProvider.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/TraceableThisAliasProvider.java deleted file mode 100644 index 185b506a2fe..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/TraceableThisAliasProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.k2js.translate.context; - -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; - -public class TraceableThisAliasProvider extends AliasingContext.AbstractThisAliasProvider { - private final ClassOrNamespaceDescriptor descriptor; - private final JsNameRef thisRef; - private boolean thisWasCaptured; - - public boolean wasThisCaptured() { - return thisWasCaptured; - } - - public TraceableThisAliasProvider(@NotNull ClassOrNamespaceDescriptor descriptor, @NotNull JsNameRef thisRef) { - this.descriptor = descriptor; - this.thisRef = thisRef; - } - - @Nullable - public JsNameRef getRefIfWasCaptured() { - return thisWasCaptured ? thisRef : null; - } - - @Nullable - @Override - public JsNameRef get(@NotNull DeclarationDescriptor unnormalizedDescriptor) { - if (descriptor == normalize(unnormalizedDescriptor)) { - thisWasCaptured = true; - return thisRef; - } - - return null; - } -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java index 3f584075e1f..165a83806c2 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.Named; import org.jetbrains.jet.lang.psi.JetExpression; @@ -32,6 +33,7 @@ import java.util.HashMap; import java.util.Map; import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForElement; +import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor; /** * All the info about the state of the translation process. @@ -43,15 +45,15 @@ public class TranslationContext { private final StaticContext staticContext; @NotNull private final AliasingContext aliasingContext; + @Nullable + private final UsageTracker usageTracker; @NotNull - public static TranslationContext rootContext(@NotNull StaticContext staticContext) { - JsProgram program = staticContext.getProgram(); - JsBlock globalBlock = program.getGlobalBlock(); - DynamicContext rootDynamicContext = DynamicContext.rootContext(staticContext.getRootScope(), globalBlock); + public static TranslationContext rootContext(@NotNull StaticContext staticContext, JsFunction rootFunction) { + DynamicContext rootDynamicContext = + DynamicContext.rootContext(rootFunction.getScope(), rootFunction.getBody()); AliasingContext rootAliasingContext = AliasingContext.getCleanContext(); - return new TranslationContext(staticContext, - rootDynamicContext, rootAliasingContext); + return new TranslationContext(staticContext, rootDynamicContext, rootAliasingContext, null); } private final HashMap expressionToTempConstVariableCache = new HashMap(); @@ -62,55 +64,60 @@ public class TranslationContext { private TranslationContext(@NotNull StaticContext staticContext, @NotNull DynamicContext dynamicContext, - @NotNull AliasingContext aliasingContext) { + @NotNull AliasingContext aliasingContext, + @Nullable UsageTracker usageTracker) { this.dynamicContext = dynamicContext; this.staticContext = staticContext; this.aliasingContext = aliasingContext; + this.usageTracker = usageTracker; } private TranslationContext(@NotNull TranslationContext parent, @NotNull AliasingContext aliasingContext) { dynamicContext = parent.dynamicContext; staticContext = parent.staticContext; this.aliasingContext = aliasingContext; + usageTracker = parent.usageTracker; + } + + public UsageTracker usageTracker() { + return usageTracker; } public DynamicContext dynamicContext() { return dynamicContext; } - @NotNull - private TranslationContext contextWithScope(@NotNull JsScope newScope, @NotNull JsBlock block) { - return contextWithScope(newScope, block, aliasingContext); - } - @NotNull public TranslationContext contextWithScope(@NotNull JsFunction fun) { - return contextWithScope(fun, aliasingContext); + return contextWithScope(fun, aliasingContext, usageTracker); } @NotNull - protected TranslationContext contextWithScope(@NotNull JsScope newScope, @NotNull JsBlock block, @NotNull AliasingContext aliasingContext) { - return new TranslationContext(staticContext, DynamicContext.newContext(newScope, block), aliasingContext); + private TranslationContext contextWithScope(@NotNull JsScope newScope, + @NotNull JsBlock block, + @NotNull AliasingContext aliasingContext, + @Nullable UsageTracker usageTracker) { + return new TranslationContext(staticContext, DynamicContext.newContext(newScope, block), aliasingContext, usageTracker); } @NotNull - public TranslationContext contextWithScope(@NotNull JsFunction fun, @NotNull AliasingContext aliasingContext) { - return contextWithScope(fun.getScope(), fun.getBody(), aliasingContext); + public TranslationContext contextWithScope(@NotNull JsFunction fun, @NotNull AliasingContext aliasingContext, @Nullable UsageTracker usageTracker) { + return contextWithScope(fun.getScope(), fun.getBody(), aliasingContext, usageTracker); } @NotNull public TranslationContext innerBlock(@NotNull JsBlock block) { - return new TranslationContext(staticContext, dynamicContext.innerBlock(block), aliasingContext); + return new TranslationContext(staticContext, dynamicContext.innerBlock(block), aliasingContext, usageTracker); } @NotNull public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) { - return contextWithScope(getScopeForDescriptor(descriptor), getBlockForDescriptor(descriptor)); + return contextWithScope(getScopeForDescriptor(descriptor), getBlockForDescriptor(descriptor), aliasingContext, usageTracker); } @NotNull public TranslationContext innerContextWithThisAliased(@NotNull DeclarationDescriptor correspondingDescriptor, @NotNull JsName alias) { - return new TranslationContext(this, aliasingContext.inner(correspondingDescriptor, alias)); + return new TranslationContext(this, aliasingContext.inner(correspondingDescriptor, alias.makeRef())); } @NotNull @@ -119,7 +126,7 @@ public class TranslationContext { } @NotNull - public TranslationContext innerContextWithDescriptorsAliased(@NotNull Map aliases) { + public TranslationContext innerContextWithDescriptorsAliased(@NotNull Map aliases) { return new TranslationContext(this, aliasingContext.withDescriptorsAliased(aliases)); } @@ -133,11 +140,6 @@ public class TranslationContext { } } - @NotNull - public TranslationContext newDeclaration(@NotNull PsiElement element) { - return newDeclaration(getDescriptorForElement(bindingContext(), element)); - } - @NotNull public BindingContext bindingContext() { return staticContext.getBindingContext(); @@ -156,14 +158,9 @@ public class TranslationContext { @NotNull public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) { - JsName alias = aliasingContext.getAliasForDescriptor(descriptor); - if (alias != null) { - return alias; - } return staticContext.getNameForDescriptor(descriptor); } - //TODO: util @NotNull public JsStringLiteral nameToLiteral(@NotNull Named named) { return program().getStringLiteral(named.getName().asString()); @@ -174,7 +171,6 @@ public class TranslationContext { return staticContext.getQualifierForDescriptor(descriptor); } - //TODO: review all invocation with notnull parameters @NotNull public TemporaryVariable declareTemporary(@Nullable JsExpression initExpression) { return dynamicContext.declareTemporary(initExpression); @@ -240,14 +236,29 @@ public class TranslationContext { dynamicContext.jsBlock().getStatements().add(statement); } - @NotNull - public AliasingContext.ThisAliasProvider thisAliasProvider() { - return aliasingContext().thisAliasProvider; + public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) { + if (usageTracker != null && descriptor instanceof ClassDescriptor) { + usageTracker.triggerUsed(descriptor); + } + return aliasingContext.getAliasForDescriptor(descriptor); } @NotNull public JsExpression getThisObject(@NotNull DeclarationDescriptor descriptor) { - JsNameRef ref = thisAliasProvider().get(descriptor); - return ref == null ? JsLiteral.THIS : ref; + DeclarationDescriptor effectiveDescriptor; + if (descriptor instanceof CallableDescriptor) { + effectiveDescriptor = getExpectedReceiverDescriptor((CallableDescriptor) descriptor); + assert effectiveDescriptor != null; + } + else { + effectiveDescriptor = descriptor; + } + + if (usageTracker != null) { + usageTracker.triggerUsed(effectiveDescriptor); + } + + JsExpression alias = aliasingContext.getAliasForDescriptor(effectiveDescriptor); + return alias == null ? JsLiteral.THIS : alias; } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.java new file mode 100644 index 00000000000..6b3e9439b6e --- /dev/null +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.translate.context; + +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; + +public class UsageTracker { + private final DeclarationDescriptor trackedDescriptor; + private boolean used; + + public UsageTracker(DeclarationDescriptor trackedDescriptor) { + this.trackedDescriptor = trackedDescriptor; + } + + public boolean isUsed() { + return used; + } + + public void triggerUsed(DeclarationDescriptor descriptor) { + if (trackedDescriptor == descriptor) { + used = true; + } + } +} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java index 8a09990a7c9..58b0149d219 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java @@ -38,7 +38,6 @@ import java.util.*; import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType; -import static org.jetbrains.k2js.translate.general.Translation.translateClassDeclaration; import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; /** @@ -86,11 +85,13 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { } private static class OpenClassInfo { + private final ClassDescriptor descriptor; private final JetClass declaration; private final JsNameRef label; private final JsNameRef qualifiedLabel; - private OpenClassInfo(JetClass declaration, JsNameRef label, JsNameRef qualifiedLabel) { + private OpenClassInfo(JetClass declaration, ClassDescriptor descriptor, JsNameRef label, JsNameRef qualifiedLabel) { + this.descriptor = descriptor; this.declaration = declaration; this.label = label; this.qualifiedLabel = qualifiedLabel; @@ -151,7 +152,8 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { Iterator it = sortedOpenClasses.descendingIterator(); while (it.hasNext()) { OpenClassInfo item = it.next(); - JsExpression translatedDeclaration = translateClassDeclaration(item.declaration, classDescriptorToLabel, context()); + JsExpression translatedDeclaration = + new ClassTranslator(item.declaration, item.descriptor, classDescriptorToLabel, context()).translate(); generate(item, propertyInitializers, translatedDeclaration, vars); } } @@ -166,7 +168,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { }; for (Pair item : finalList) { - new ClassTranslator(item.first, aliasingMap, context()).translateClassOrObjectCreation(item.second); + new ClassTranslator(item.first, aliasingMap, context()).translate(item.second); } } @@ -199,8 +201,8 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { else { String label = localLabelGenerator.generate(); JsNameRef labelRef = dummyFunction.getScope().declareName(label).makeRef(); - OpenClassInfo - item = new OpenClassInfo((JetClass) declaration, labelRef, new JsNameRef(labelRef.getIdent(), declarationsObjectRef)); + OpenClassInfo item = new OpenClassInfo((JetClass) declaration, descriptor, labelRef, + new JsNameRef(labelRef.getIdent(), declarationsObjectRef)); openList.add(item); openClassDescriptorToItem.put(descriptor, item); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java index f3c01262e40..9491ed3fc8c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java @@ -17,6 +17,8 @@ package org.jetbrains.k2js.translate.declaration; import com.google.dart.compiler.backend.js.ast.*; +import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.Trinity; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,10 +29,11 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetObjectLiteralExpression; import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.k2js.translate.LabelGenerator; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; -import org.jetbrains.k2js.translate.general.Translation; +import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator; import org.jetbrains.k2js.translate.utils.AnnotationsUtils; import java.util.ArrayList; @@ -38,8 +41,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType; -import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isNotAny; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; +import static org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator.createPlace; import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContainingClass; @@ -50,9 +53,6 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.getQualifiedRe * Generates a definition of a single class. */ public final class ClassTranslator extends AbstractTranslator { - @NotNull - private final DeclarationBodyVisitor declarationBodyVisitor = new DeclarationBodyVisitor(); - @NotNull private final JetClassOrObject classDeclaration; @@ -62,23 +62,16 @@ public final class ClassTranslator extends AbstractTranslator { @Nullable private final ClassAliasingMap aliasingMap; - @NotNull - public static JsExpression generateClassCreation(@NotNull JetClassOrObject classDeclaration, - @NotNull ClassAliasingMap aliasingMap, - @NotNull TranslationContext context) { - return new ClassTranslator(classDeclaration, aliasingMap, context).translateClassOrObjectCreation(context); - } - @NotNull public static JsExpression generateClassCreation(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { - return new ClassTranslator(classDeclaration, null, context).translateClassOrObjectCreation(context); + return new ClassTranslator(classDeclaration, null, context).translate(context); } @NotNull public static JsExpression generateClassCreation(@NotNull JetClassOrObject classDeclaration, @NotNull ClassDescriptor descriptor, @NotNull TranslationContext context) { - return new ClassTranslator(classDeclaration, descriptor, null, context).translateClassOrObjectCreation(context); + return new ClassTranslator(classDeclaration, descriptor, null, context).translate(context); } @NotNull @@ -107,28 +100,28 @@ public final class ClassTranslator extends AbstractTranslator { private JsExpression translateObjectLiteralExpression() { ClassDescriptor containingClass = getContainingClass(descriptor); if (containingClass == null) { - return translateClassOrObjectCreation(context()); + return translate(context()); } - return translateAsObjectCreationExpressionWithEnclosingThisSaved(containingClass); - } - - @NotNull - private JsExpression translateAsObjectCreationExpressionWithEnclosingThisSaved(@NotNull ClassDescriptor containingClass) { return context().literalFunctionTranslator().translate(containingClass, classDeclaration, descriptor, this); } @NotNull - public JsExpression translateClassOrObjectCreation(@NotNull TranslationContext declarationContext) { + public JsExpression translate() { + return translate(context()); + } + + @NotNull + public JsExpression translate(@NotNull TranslationContext declarationContext) { JsInvocation createInvocation = context().namer().classCreateInvocation(descriptor); - translateClassOrObjectCreation(createInvocation, declarationContext); + translate(createInvocation, declarationContext); return createInvocation; } - public void translateClassOrObjectCreation(@NotNull JsInvocation createInvocation) { - translateClassOrObjectCreation(createInvocation, context()); + public void translate(@NotNull JsInvocation createInvocation) { + translate(createInvocation, context()); } - private void translateClassOrObjectCreation(@NotNull JsInvocation createInvocation, @NotNull TranslationContext context) { + private void translate(@NotNull JsInvocation createInvocation, @NotNull TranslationContext context) { addSuperclassReferences(createInvocation); addClassOwnDeclarations(createInvocation, context); } @@ -137,40 +130,80 @@ public final class ClassTranslator extends AbstractTranslator { return descriptor.getKind().equals(ClassKind.TRAIT); } - private void addClassOwnDeclarations(@NotNull JsInvocation jsClassDeclaration, @NotNull TranslationContext classDeclarationContext) { - JsObjectLiteral properties = new JsObjectLiteral(true); - List propertyList = properties.getPropertyInitializers(); + private void addClassOwnDeclarations(@NotNull JsInvocation jsClassDeclaration, @NotNull final TranslationContext declarationContext) { + final List properties = new SmartList(); + + final List staticProperties; + boolean isTopLevelDeclaration = context() == declarationContext; + if (!isTopLevelDeclaration) { + staticProperties = null; + } + else if (descriptor.getKind().isObject()) { + staticProperties = null; + declarationContext.literalFunctionTranslator() + .setDefinitionPlace(new NotNullLazyValue, LabelGenerator, JsExpression>>() { + @Override + @NotNull + public Trinity, LabelGenerator, JsExpression> compute() { + return createPlace(properties, context().getThisObject(descriptor)); + } + }); + } + else { + staticProperties = new SmartList(); + declarationContext.literalFunctionTranslator() + .setDefinitionPlace(new NotNullLazyValue, LabelGenerator, JsExpression>>() { + @Override + @NotNull + public Trinity, LabelGenerator, JsExpression> compute() { + return createPlace(staticProperties, getQualifiedReference(declarationContext, descriptor)); + } + }); + } + if (!isTrait()) { - JsFunction initializer = Translation.generateClassInitializerMethod(classDeclaration, classDeclarationContext); + JsFunction initializer = new ClassInitializerTranslator(classDeclaration, declarationContext).generateInitializeMethod(); if (context().isEcma5()) { jsClassDeclaration.getArguments().add(initializer.getBody().getStatements().isEmpty() ? JsLiteral.NULL : initializer); } else { - propertyList.add(new JsPropertyInitializer(Namer.initializeMethodReference(), initializer)); + properties.add(new JsPropertyInitializer(Namer.initializeMethodReference(), initializer)); } } - propertyList.addAll(translatePropertiesAsConstructorParameters(classDeclarationContext)); - propertyList.addAll(declarationBodyVisitor.traverseClass(classDeclaration, classDeclarationContext)); + translatePropertiesAsConstructorParameters(declarationContext, properties); + new DeclarationBodyVisitor(properties).traverseContainer(classDeclaration, declarationContext); - if (!propertyList.isEmpty() || !context().isEcma5()) { - jsClassDeclaration.getArguments().add(properties); + if (isTopLevelDeclaration) { + declarationContext.literalFunctionTranslator().setDefinitionPlace(null); + } + + boolean hasStaticProperties = staticProperties != null && !staticProperties.isEmpty(); + if (!properties.isEmpty() || hasStaticProperties) { + jsClassDeclaration.getArguments().add(properties.isEmpty() ? JsLiteral.NULL : new JsObjectLiteral(properties, true)); + } + if (hasStaticProperties) { + jsClassDeclaration.getArguments().add(new JsObjectLiteral(staticProperties, true)); } } private void addSuperclassReferences(@NotNull JsInvocation jsClassDeclaration) { List superClassReferences = getSupertypesNameReferences(); - List expressions = jsClassDeclaration.getArguments(); - if (context().isEcma5()) { - if (superClassReferences.isEmpty()) { + if (superClassReferences.isEmpty()) { + if (!isTrait() || context().isEcma5()) { jsClassDeclaration.getArguments().add(JsLiteral.NULL); - return; - } - else if (superClassReferences.size() > 1) { - JsArrayLiteral arrayLiteral = new JsArrayLiteral(); - jsClassDeclaration.getArguments().add(arrayLiteral); - expressions = arrayLiteral.getExpressions(); } + return; + } + + List expressions; + if (superClassReferences.size() > 1) { + JsArrayLiteral arrayLiteral = new JsArrayLiteral(); + jsClassDeclaration.getArguments().add(arrayLiteral); + expressions = arrayLiteral.getExpressions(); + } + else { + expressions = jsClassDeclaration.getArguments(); } for (JsExpression superClassReference : superClassReferences) { @@ -231,20 +264,13 @@ public final class ClassTranslator extends AbstractTranslator { return getQualifiedReference(context(), superClassDescriptor); } - @NotNull - private List translatePropertiesAsConstructorParameters(@NotNull TranslationContext classDeclarationContext) { - List parameters = getPrimaryConstructorParameters(classDeclaration); - if (parameters.isEmpty()) { - return Collections.emptyList(); - } - - List result = new SmartList(); - for (JetParameter parameter : parameters) { + private void translatePropertiesAsConstructorParameters(@NotNull TranslationContext classDeclarationContext, + @NotNull List result) { + for (JetParameter parameter : getPrimaryConstructorParameters(classDeclaration)) { PropertyDescriptor descriptor = getPropertyDescriptorForConstructorParameter(bindingContext(), parameter); if (descriptor != null) { PropertyTranslator.translateAccessors(descriptor, result, classDeclarationContext); } } - return result; } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java index 8ed7b069dc2..ade4008bede 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java @@ -36,9 +36,14 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescrip import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForObjectDeclaration; public class DeclarationBodyVisitor extends TranslatorVisitor { - protected final List result = new SmartList(); + protected final List result; public DeclarationBodyVisitor() { + this(new SmartList()); + } + + public DeclarationBodyVisitor(List result) { + this.result = result; } @NotNull @@ -46,15 +51,6 @@ public class DeclarationBodyVisitor extends TranslatorVisitor { return result; } - @NotNull - public List traverseClass(@NotNull JetClassOrObject jetClass, - @NotNull TranslationContext context) { - for (JetDeclaration declaration : jetClass.getDeclarations()) { - declaration.accept(this, context); - } - return result; - } - @Override public Void visitClass(@NotNull JetClass expression, @NotNull TranslationContext context) { return null; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java index 12373c5d176..81ec34d97ce 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java @@ -62,7 +62,7 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { if (rootNamespaceDefinition == null) { rootNamespaceDefinition = getRootPackage(descriptorToDefineInvocation, descriptor); } - translator = new NamespaceTranslator(descriptor, classDeclarationTranslator, context()); + translator = new NamespaceTranslator(descriptor, classDeclarationTranslator, descriptorToDefineInvocation, context()); descriptorToTranslator.put(descriptor, translator); } @@ -88,7 +88,6 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { translator.add(descriptorToDefineInvocation, result); } - vars.addIfHasInitializer(context().literalFunctionTranslator().getDeclaration()); vars.addIfHasInitializer(classDeclarationTranslator.getDeclaration()); vars.addIfHasInitializer(getDeclaration(rootNamespaceDefinition)); return result; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java index c9e02a8e73e..f069789be71 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java @@ -17,17 +17,22 @@ package org.jetbrains.k2js.translate.declaration; import com.google.dart.compiler.backend.js.ast.*; +import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.Trinity; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.k2js.translate.LabelGenerator; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.initializer.InitializerUtils; import org.jetbrains.k2js.translate.initializer.InitializerVisitor; +import org.jetbrains.k2js.translate.utils.AnnotationsUtils; +import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils; @@ -36,9 +41,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import static org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator.createPlace; import static org.jetbrains.k2js.translate.initializer.InitializerUtils.generateInitializerForProperty; -import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.isPredefinedObject; -import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForElement; import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptor; final class NamespaceTranslator extends AbstractTranslator { @@ -49,22 +53,49 @@ final class NamespaceTranslator extends AbstractTranslator { private final FileDeclarationVisitor visitor; - NamespaceTranslator(@NotNull NamespaceDescriptor descriptor, + private final NotNullLazyValue, LabelGenerator, JsExpression>> definitionPlace; + + NamespaceTranslator(@NotNull final NamespaceDescriptor descriptor, @NotNull ClassDeclarationTranslator classDeclarationTranslator, + @NotNull final Map> descriptorToDefineInvocation, @NotNull TranslationContext context) { super(context.newDeclaration(descriptor)); + this.descriptor = descriptor; this.classDeclarationTranslator = classDeclarationTranslator; visitor = new FileDeclarationVisitor(); + + definitionPlace = new NotNullLazyValue, LabelGenerator, JsExpression>>() { + @Override + @NotNull + public Trinity, LabelGenerator, JsExpression> compute() { + List defineInvocation = descriptorToDefineInvocation.get(descriptor); + if (defineInvocation == null) { + defineInvocation = createDefinitionPlace(null, descriptorToDefineInvocation); + } + + return createPlace(getListFromPlace(defineInvocation), TranslationUtils.getQualifiedReference(context(), descriptor)); + } + }; } public void translate(JetFile file) { + context().literalFunctionTranslator().setDefinitionPlace(definitionPlace); for (JetDeclaration declaration : file.getDeclarations()) { - if (!isPredefinedObject(getDescriptorForElement(bindingContext(), declaration))) { + if (!AnnotationsUtils.isPredefinedObject(BindingUtils.getDescriptorForElement(bindingContext(), declaration))) { declaration.accept(visitor, context()); } } + context().literalFunctionTranslator().setDefinitionPlace(null); + } + + private List createDefinitionPlace(@Nullable JsExpression initializer, + Map> descriptorToDefineInvocation) { + List place = createDefineInvocation(initializer, new JsObjectLiteral(visitor.getResult(), true)); + descriptorToDefineInvocation.put(descriptor, place); + addToParent((NamespaceDescriptor) descriptor.getContainingDeclaration(), getEntry(descriptor, place), descriptorToDefineInvocation); + return place; } public void add(@NotNull Map> descriptorToDefineInvocation, @@ -83,20 +114,26 @@ final class NamespaceTranslator extends AbstractTranslator { List defineInvocation = descriptorToDefineInvocation.get(descriptor); if (defineInvocation == null) { - defineInvocation = createDefineInvocation(initializer, new JsObjectLiteral(visitor.getResult(), true)); - descriptorToDefineInvocation.put(descriptor, defineInvocation); - addToParent((NamespaceDescriptor) descriptor.getContainingDeclaration(), getEntry(descriptor, defineInvocation), - descriptorToDefineInvocation); + createDefinitionPlace(initializer, descriptorToDefineInvocation); } else { if (context().isEcma5() && initializer != null) { assert defineInvocation.get(0) == JsLiteral.NULL; defineInvocation.set(0, initializer); } - ((JsObjectLiteral) defineInvocation.get(context().isEcma5() ? 1 : 0)).getPropertyInitializers().addAll(visitor.getResult()); + + List listFromPlace = getListFromPlace(defineInvocation); + // if equals, so, inner functions was added + if (listFromPlace != visitor.getResult()) { + listFromPlace.addAll(visitor.getResult()); + } } } + private List getListFromPlace(List defineInvocation) { + return ((JsObjectLiteral) defineInvocation.get(context().isEcma5() ? 1 : 0)).getPropertyInitializers(); + } + private List createDefineInvocation(@Nullable JsExpression initializer, @NotNull JsObjectLiteral members) { if (context().isEcma5()) { return Arrays.asList(initializer == null ? JsLiteral.NULL : initializer, members); @@ -126,8 +163,7 @@ final class NamespaceTranslator extends AbstractTranslator { JsPropertyInitializer entry, Map> descriptorToDefineInvocation) { while (!addEntryIfParentExists(parentDescriptor, entry, descriptorToDefineInvocation)) { - List defineInvocation = - createDefineInvocation(null, new JsObjectLiteral(new SmartList(entry), true)); + List defineInvocation = createDefineInvocation(null, new JsObjectLiteral(new SmartList(entry), true)); entry = getEntry(parentDescriptor, defineInvocation); descriptorToDefineInvocation.put(parentDescriptor, defineInvocation); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index a39eefdeded..a3bc1f69eec 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -20,6 +20,8 @@ import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; @@ -36,6 +38,7 @@ import org.jetbrains.k2js.translate.reference.*; import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.mutator.AssignToExpressionMutator; +import java.util.Collections; import java.util.List; import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression; @@ -130,10 +133,19 @@ public final class ExpressionVisitor extends TranslatorVisitor { @NotNull // assume it is a local variable declaration public JsNode visitProperty(@NotNull JetProperty expression, @NotNull TranslationContext context) { - DeclarationDescriptor descriptor = getDescriptorForElement(context.bindingContext(), expression); - JsName jsPropertyName = context.getNameForDescriptor(descriptor); - JsExpression jsInitExpression = translateInitializerForProperty(expression, context); - return newVar(jsPropertyName, jsInitExpression); + VariableDescriptor descriptor = context.bindingContext().get(BindingContext.VARIABLE, expression); + assert descriptor != null; + JsExpression initializer = translateInitializerForProperty(expression, context); + JsName name = context.getNameForDescriptor(descriptor); + if (descriptor.isVar() && context.bindingContext().get(BindingContext.CAPTURED_IN_CLOSURE, descriptor) != null) { + // well, wrap it + JsNameRef alias = new JsNameRef("v", new JsNameRef(name)); + initializer = new JsObjectLiteral( + Collections.singletonList(new JsPropertyInitializer(alias, initializer == null ? JsLiteral.NULL : initializer))); + context.aliasingContext().registerAlias(descriptor, alias); + } + + return newVar(name, initializer); } @Override @@ -319,15 +331,24 @@ public final class ExpressionVisitor extends TranslatorVisitor { @Override @NotNull - public JsNode visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, - @NotNull TranslationContext context) { - return context.literalFunctionTranslator().translate(expression); + public JsNode visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, @NotNull TranslationContext context) { + FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression.getFunctionLiteral()); + return context.literalFunctionTranslator().translate(expression.getFunctionLiteral(), descriptor, context); } @Override @NotNull - public JsNode visitThisExpression(@NotNull JetThisExpression expression, - @NotNull TranslationContext context) { + public JsNode visitNamedFunction(@NotNull JetNamedFunction expression, @NotNull TranslationContext context) { + FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression); + JsExpression alias = context.literalFunctionTranslator().translate(expression, descriptor, context); + JsName name = context.scope().declareFreshName(descriptor.getName().asString()); + context.aliasingContext().registerAlias(descriptor, name.makeRef()); + return new JsVars(new JsVars.JsVar(name, alias)); + } + + @Override + @NotNull + public JsNode visitThisExpression(@NotNull JetThisExpression expression, @NotNull TranslationContext context) { DeclarationDescriptor thisExpression = getDescriptorForReferenceExpression(context.bindingContext(), expression.getInstanceReference()); assert thisExpression != null : "This expression must reference a descriptor: " + expression.getText(); @@ -381,11 +402,4 @@ public final class ExpressionVisitor extends TranslatorVisitor { JsExpression value = ClassTranslator.generateClassCreation(expression, context); return newVar(propertyName, value); } - - @Override - @NotNull - public JsNode visitNamedFunction(@NotNull JetNamedFunction function, - @NotNull TranslationContext context) { - return FunctionTranslator.newInstance(function, context).translateAsLocalFunction(); - } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java index 5a07b32652e..b5cf99828d3 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java @@ -30,7 +30,6 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFunctionLiteral; -import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; @@ -64,8 +63,7 @@ public final class FunctionTranslator extends AbstractTranslator { @NotNull private final FunctionDescriptor descriptor; - private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration, - @NotNull TranslationContext context) { + private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration, @NotNull TranslationContext context) { super(context); this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration); this.functionDeclaration = functionDeclaration; @@ -95,15 +93,7 @@ public final class FunctionTranslator extends AbstractTranslator { @NotNull private TranslationContext getContextWithFunctionBodyBlock() { - return context().newDeclaration(functionDeclaration).innerBlock(functionObject.getBody()); - } - - @NotNull - public JsFunction translateAsLocalFunction() { - JsName functionName = context().getNameForElement(functionDeclaration); - generateFunctionObject(); - functionObject.setName(functionName); - return functionObject; + return context().contextWithScope(functionObject); } @NotNull @@ -114,7 +104,7 @@ public final class FunctionTranslator extends AbstractTranslator { @NotNull public JsPropertyInitializer translateAsMethod() { - JsName functionName = context().getNameForElement(functionDeclaration); + JsName functionName = context().getNameForDescriptor(descriptor); generateFunctionObject(); return new JsPropertyInitializer(functionName.makeRef(), functionObject); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerDeclarationTranslator.java index 1ac1768dbbe..c3f0c28df34 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerDeclarationTranslator.java @@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; @@ -35,12 +36,12 @@ abstract class InnerDeclarationTranslator { protected final TranslationContext context; protected final JsFunction fun; - public InnerDeclarationTranslator(@NotNull JetElement declaration, + public InnerDeclarationTranslator(@NotNull JetElement element, @NotNull DeclarationDescriptor descriptor, @NotNull TranslationContext context, @NotNull JsFunction fun) { this.context = context; - closureContext = ClosureUtils.captureClosure(context.bindingContext(), declaration, descriptor); + closureContext = ClosureUtils.captureClosure(context.bindingContext(), element, descriptor); this.fun = fun; } @@ -48,10 +49,7 @@ abstract class InnerDeclarationTranslator { return Collections.emptyList(); } - @NotNull - public abstract JsExpression translate(@NotNull JsNameRef nameRef); - - protected JsExpression translate(@NotNull JsNameRef nameRef, @Nullable JsExpression self) { + public JsExpression translate(@NotNull JsNameRef nameRef, @Nullable JsExpression self) { if (closureContext.getDescriptors().isEmpty() && self == JsLiteral.NULL) { return createExpression(nameRef, self); } @@ -62,9 +60,9 @@ abstract class InnerDeclarationTranslator { } } - protected abstract JsExpression createExpression(JsNameRef nameRef, JsExpression self); + protected abstract JsExpression createExpression(@NotNull JsNameRef nameRef, @Nullable JsExpression self); - protected abstract JsInvocation createInvocation(JsNameRef nameRef, JsExpression self); + protected abstract JsInvocation createInvocation(@NotNull JsNameRef nameRef, @Nullable JsExpression self); private void addCapturedValueParameters(JsInvocation bind) { if (closureContext.getDescriptors().isEmpty()) { @@ -72,8 +70,15 @@ abstract class InnerDeclarationTranslator { } List expressions = getCapturedValueParametersList(bind); - for (VariableDescriptor variableDescriptor : closureContext.getDescriptors()) { - JsName name = context.getNameForDescriptor(variableDescriptor); + for (CallableDescriptor descriptor : closureContext.getDescriptors()) { + JsName name; + if (descriptor instanceof VariableDescriptor) { + name = context.getNameForDescriptor(descriptor); + } + else { + name = ((JsNameRef) context.getAliasForDescriptor(descriptor)).getName(); + assert name != null; + } fun.getParameters().add(new JsParameter(name)); expressions.add(name.makeRef()); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerFunctionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerFunctionTranslator.java index b5bef46aaac..97e1f1ee3a4 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerFunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerFunctionTranslator.java @@ -18,6 +18,7 @@ package org.jetbrains.k2js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; @@ -29,38 +30,32 @@ import java.util.List; class InnerFunctionTranslator extends InnerDeclarationTranslator { private final FunctionDescriptor descriptor; - public InnerFunctionTranslator(@NotNull JetElement declaration, + public InnerFunctionTranslator(@NotNull JetElement element, @NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context, @NotNull JsFunction fun) { - super(declaration, descriptor, context, fun); + super(element, descriptor, context, fun); this.descriptor = descriptor; } - public boolean isLocalVariablesAffected() { - return closureContext.isLocalVariablesAffected(); - } - @Override protected List getValueParameters() { return descriptor.getValueParameters(); } - @Override + @SuppressWarnings("MethodOverloadsMethodOfSuperclass") @NotNull - public JsExpression translate(@NotNull JsNameRef nameRef) { - JsExpression result = translate(nameRef, getThis()); - FunctionTranslator.addParameters(fun.getParameters(), descriptor, context); - return result; + public JsExpression translate(@NotNull JsNameRef nameRef, @NotNull TranslationContext outerContext) { + return translate(nameRef, getThis(outerContext)); } @Override - protected JsExpression createExpression(JsNameRef nameRef, JsExpression self) { + protected JsExpression createExpression(@NotNull JsNameRef nameRef, @Nullable JsExpression self) { return nameRef; } @Override - protected JsInvocation createInvocation(JsNameRef nameRef, JsExpression self) { + protected JsInvocation createInvocation(@NotNull JsNameRef nameRef, @Nullable JsExpression self) { JsInvocation bind = new JsInvocation(context.namer().kotlin(getBindMethodName())); bind.getArguments().add(nameRef); bind.getArguments().add(self); @@ -68,10 +63,10 @@ class InnerFunctionTranslator extends InnerDeclarationTranslator { } @NotNull - private JsExpression getThis() { + private JsExpression getThis(TranslationContext outerContext) { ClassDescriptor outerClassDescriptor = closureContext.outerClassDescriptor; if (outerClassDescriptor != null && descriptor.getReceiverParameter() == null) { - return JsLiteral.THIS; + return outerContext.getThisObject(outerClassDescriptor); } return JsLiteral.NULL; @@ -80,16 +75,20 @@ class InnerFunctionTranslator extends InnerDeclarationTranslator { @NotNull private String getBindMethodName() { if (closureContext.getDescriptors().isEmpty()) { - return getValueParameters().isEmpty() ? "b3" : "b4"; + return !hasArguments() ? "b3" : "b4"; } else { - return getValueParameters().isEmpty() ? (closureContext.getDescriptors().size() == 1 ? "b0" : "b1") : "b2"; + return !hasArguments() ? (closureContext.getDescriptors().size() == 1 ? "b0" : "b1") : "b2"; } } + private boolean hasArguments() { + return !getValueParameters().isEmpty() || descriptor.getReceiverParameter() != null; + } + @Override protected List getCapturedValueParametersList(JsInvocation invocation) { - if (closureContext.getDescriptors().size() > 1 || !getValueParameters().isEmpty()) { + if (closureContext.getDescriptors().size() > 1 || hasArguments()) { JsArrayLiteral values = new JsArrayLiteral(); invocation.getArguments().add(values); return values.getExpressions(); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerObjectTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerObjectTranslator.java index 0af41ec18e4..b53f8e20d0c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerObjectTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerObjectTranslator.java @@ -18,35 +18,25 @@ package org.jetbrains.k2js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.psi.JetClassOrObject; -import org.jetbrains.k2js.translate.context.TraceableThisAliasProvider; +import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.k2js.translate.context.TranslationContext; class InnerObjectTranslator extends InnerDeclarationTranslator { - public InnerObjectTranslator(@NotNull JetClassOrObject declaration, @NotNull ClassDescriptor descriptor, @NotNull TranslationContext context, @NotNull JsFunction fun) { - super(declaration, descriptor, context, fun); + public InnerObjectTranslator(@NotNull JetElement element, @NotNull ClassDescriptor descriptor, @NotNull TranslationContext context, @NotNull JsFunction fun) { + super(element, descriptor, context, fun); } @Override - protected JsExpression createExpression(JsNameRef nameRef, JsExpression self) { + protected JsExpression createExpression(@NotNull JsNameRef nameRef, @Nullable JsExpression self) { return createInvocation(nameRef, self); } @Override - @NotNull - public JsExpression translate(@NotNull JsNameRef nameRef) { - return super.translate(nameRef, thisAliasProvider().getRefIfWasCaptured()); - } - - private TraceableThisAliasProvider thisAliasProvider() { - return ((TraceableThisAliasProvider) context.thisAliasProvider()); - } - - @Override - protected JsInvocation createInvocation(JsNameRef nameRef, JsExpression self) { + protected JsInvocation createInvocation(@NotNull JsNameRef nameRef, @Nullable JsExpression self) { JsInvocation invocation = new JsInvocation(nameRef); - if (thisAliasProvider().wasThisCaptured()) { + if (self != null) { fun.getParameters().add(new JsParameter(((JsNameRef) self).getName())); invocation.getArguments().add(JsLiteral.THIS); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/LiteralFunctionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/LiteralFunctionTranslator.java index 08f5001224b..81d9d199c38 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/LiteralFunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/LiteralFunctionTranslator.java @@ -17,79 +17,107 @@ package org.jetbrains.k2js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; +import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.Trinity; +import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.psi.JetClassBody; import org.jetbrains.jet.lang.psi.JetClassOrObject; -import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; +import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.k2js.translate.LabelGenerator; +import org.jetbrains.k2js.translate.context.AliasingContext; import org.jetbrains.k2js.translate.context.Namer; -import org.jetbrains.k2js.translate.context.TraceableThisAliasProvider; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.context.UsageTracker; import org.jetbrains.k2js.translate.declaration.ClassTranslator; +import org.jetbrains.k2js.translate.initializer.InitializerUtils; -import java.util.ArrayList; import java.util.List; -import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar; -import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor; import static org.jetbrains.k2js.translate.utils.FunctionBodyTranslator.translateFunctionBody; +import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor; -// todo easy incremental compiler implementation - generated functions should be inside corresponding class/namespace definition public class LiteralFunctionTranslator { - private final List properties = new ArrayList(); - private final LabelGenerator labelGenerator = new LabelGenerator('f'); - private final JsNameRef containingVarRef = new JsNameRef("_f"); - private TranslationContext rootContext; + private final Stack, LabelGenerator, JsExpression>>> definitionPlaces = + new Stack, LabelGenerator, JsExpression>>>(); + private NotNullLazyValue, LabelGenerator, JsExpression>> definitionPlace; + public void setRootContext(@NotNull TranslationContext rootContext) { assert this.rootContext == null; this.rootContext = rootContext; - JsName containingVarName = rootContext.scope().declareName(containingVarRef.getIdent()); - containingVarRef.resolve(containingVarName); } - public JsVar getDeclaration() { - return new JsVar(containingVarRef.getName(), properties.isEmpty() ? null : new JsObjectLiteral(properties, true)); + public static Trinity, LabelGenerator, JsExpression> createPlace(@NotNull List list, + @NotNull JsExpression reference) { + return Trinity.create(list, new LabelGenerator('f'), reference); } - public JsExpression translate(@NotNull JetFunctionLiteralExpression declaration) { - FunctionDescriptor descriptor = getFunctionDescriptor(rootContext.bindingContext(), declaration.getFunctionLiteral()); + public void setDefinitionPlace(@Nullable NotNullLazyValue, LabelGenerator, JsExpression>> place) { + if (place == null) { + definitionPlaces.pop(); + definitionPlace = definitionPlaces.isEmpty() ? null : definitionPlaces.peek(); + } + else { + definitionPlaces.push(place); + definitionPlace = place; + } + } + public JsExpression translate(@NotNull JetDeclarationWithBody declaration, @NotNull FunctionDescriptor descriptor, @NotNull TranslationContext outerContext) { JsFunction fun = createFunction(); TranslationContext funContext; boolean asInner; + ClassDescriptor outerClass; + AliasingContext aliasingContext = rootContext.aliasingContext(); + DeclarationDescriptor receiverDescriptor = getExpectedReceiverDescriptor(descriptor); + JsName receiverName; + if (receiverDescriptor == null) { + receiverName = null; + } + else { + receiverName = fun.getScope().declareName(Namer.getReceiverParameterName()); + aliasingContext = aliasingContext.inner(receiverDescriptor, receiverName.makeRef()); + } + if (descriptor.getContainingDeclaration() instanceof ConstructorDescriptor) { // KT-2388 asInner = true; fun.setName(fun.getScope().declareName(Namer.CALLEE_NAME)); - ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration(); - assert classDescriptor != null; - funContext = createThisTraceableContext(classDescriptor, fun, new JsNameRef("o", fun.getName().makeRef())); + outerClass = (ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration(); + assert outerClass != null; + + if (receiverDescriptor == null) { + aliasingContext = aliasingContext.inner(outerClass, new JsNameRef("o", fun.getName().makeRef())); + } + + funContext = rootContext.contextWithScope(fun, aliasingContext, new UsageTracker(outerClass)); } else { + outerClass = null; asInner = DescriptorUtils.isTopLevelDeclaration(descriptor); - funContext = rootContext.contextWithScope(fun); + + funContext = rootContext.contextWithScope(fun, aliasingContext, outerContext.usageTracker()); } - fun.getBody().getStatements().addAll(translateFunctionBody(descriptor, declaration.getFunctionLiteral(), funContext).getStatements()); + fun.getBody().getStatements().addAll(translateFunctionBody(descriptor, declaration, funContext).getStatements()); InnerFunctionTranslator translator = null; if (!asInner) { - translator = new InnerFunctionTranslator(declaration, descriptor, funContext, fun); - if (translator.isLocalVariablesAffected()) { - asInner = true; - } + translator = new InnerFunctionTranslator(declaration.asElement(), descriptor, funContext, fun); } if (asInner) { - FunctionTranslator.addParameters(fun.getParameters(), descriptor, funContext); - if (funContext.thisAliasProvider() instanceof TraceableThisAliasProvider) { - TraceableThisAliasProvider provider = (TraceableThisAliasProvider) funContext.thisAliasProvider(); - if (provider.wasThisCaptured()) { + addRegularParameters(descriptor, fun, funContext, receiverName); + if (outerClass != null) { + if (funContext.usageTracker().isUsed()) { return new JsInvocation(rootContext.namer().kotlin("assignOwner"), fun, JsLiteral.THIS); } else { @@ -97,40 +125,49 @@ public class LiteralFunctionTranslator { } } - return fun; } - return translate(translator, fun); + JsExpression result = translator.translate(createReference(fun), outerContext); + addRegularParameters(descriptor, fun, funContext, receiverName); + return result; + } + + private JsNameRef createReference(JsFunction fun) { + Trinity, LabelGenerator, JsExpression> place = definitionPlace.getValue(); + JsNameRef nameRef = new JsNameRef(place.second.generate(), place.third); + place.first.add(new JsPropertyInitializer(nameRef, InitializerUtils.toDataDescriptor(fun, rootContext))); + return nameRef; + } + + private static void addRegularParameters(FunctionDescriptor descriptor, + JsFunction fun, + TranslationContext funContext, + JsName receiverName) { + if (receiverName != null) { + fun.getParameters().add(new JsParameter(receiverName)); + } + FunctionTranslator.addParameters(fun.getParameters(), descriptor, funContext); } private JsFunction createFunction() { return new JsFunction(rootContext.scope(), new JsBlock()); } - public JsExpression translate(@NotNull ClassDescriptor containingClass, + public JsExpression translate(@NotNull ClassDescriptor outerClass, @NotNull JetClassOrObject declaration, @NotNull ClassDescriptor descriptor, @NotNull ClassTranslator classTranslator) { JsFunction fun = createFunction(); - JsName outerThisName = fun.getScope().declareName("$this"); - TranslationContext funContext = createThisTraceableContext(containingClass, fun, outerThisName.makeRef()); + JsNameRef outerClassRef = fun.getScope().declareName("$this").makeRef(); + TranslationContext funContext = rootContext + .contextWithScope(fun, rootContext.aliasingContext().inner(outerClass, outerClassRef), new UsageTracker(outerClass)); - fun.getBody().getStatements().add(new JsReturn(classTranslator.translateClassOrObjectCreation(funContext))); - return translate(new InnerObjectTranslator(declaration, descriptor, funContext, fun), fun); - } - - private JsExpression translate(@NotNull InnerDeclarationTranslator translator, @NotNull JsFunction fun) { - JsNameRef nameRef = new JsNameRef(labelGenerator.generate(), containingVarRef); - properties.add(new JsPropertyInitializer(nameRef, fun)); - return translator.translate(nameRef); - } - - private TranslationContext createThisTraceableContext(@NotNull ClassDescriptor containingClass, - @NotNull JsFunction fun, - @NotNull JsNameRef thisRef) { - return rootContext.contextWithScope(fun, rootContext.aliasingContext().inner( - new TraceableThisAliasProvider(containingClass, thisRef))); + fun.getBody().getStatements().add(new JsReturn(classTranslator.translate(funContext))); + JetClassBody body = declaration.getBody(); + assert body != null; + InnerObjectTranslator translator = new InnerObjectTranslator(body, descriptor, funContext, fun); + return translator.translate(createReference(fun), funContext.usageTracker().isUsed() ? outerClassRef : null); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java index f474310c1a4..fe765a707f3 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java @@ -31,14 +31,11 @@ import org.jetbrains.k2js.facade.exceptions.UnsupportedFeatureException; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.StaticContext; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.declaration.ClassAliasingMap; -import org.jetbrains.k2js.translate.declaration.ClassTranslator; import org.jetbrains.k2js.translate.declaration.NamespaceDeclarationTranslator; import org.jetbrains.k2js.translate.expression.ExpressionVisitor; import org.jetbrains.k2js.translate.expression.FunctionTranslator; import org.jetbrains.k2js.translate.expression.PatternTranslator; import org.jetbrains.k2js.translate.expression.WhenTranslator; -import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator; import org.jetbrains.k2js.translate.reference.CallBuilder; import org.jetbrains.k2js.translate.test.JSTestGenerator; import org.jetbrains.k2js.translate.test.JSTester; @@ -75,13 +72,6 @@ public final class Translation { return NamespaceDeclarationTranslator.translateFiles(files, context); } - @NotNull - public static JsExpression translateClassDeclaration(@NotNull JetClass classDeclaration, - @NotNull ClassAliasingMap classAliasingMap, - @NotNull TranslationContext context) { - return ClassTranslator.generateClassCreation(classDeclaration, classAliasingMap, context); - } - @NotNull public static PatternTranslator patternTranslator(@NotNull TranslationContext context) { return PatternTranslator.newInstance(context); @@ -124,14 +114,6 @@ public final class Translation { return WhenTranslator.translate(expression, context); } - //TODO: see if generate*Initializer methods fit somewhere else - @NotNull - public static JsFunction generateClassInitializerMethod(@NotNull JetClassOrObject classDeclaration, - @NotNull TranslationContext context) { - ClassInitializerTranslator classInitializerTranslator = new ClassInitializerTranslator(classDeclaration, context); - return classInitializerTranslator.generateInitializeMethod(); - } - @NotNull public static JsProgram generateAst(@NotNull BindingContext bindingContext, @NotNull Collection files, @NotNull MainCallParameters mainCallParameters, @@ -162,7 +144,7 @@ public final class Translation { List statements = rootBlock.getStatements(); statements.add(program.getStringLiteral("use strict").makeStmt()); - TranslationContext context = TranslationContext.rootContext(staticContext); + TranslationContext context = TranslationContext.rootContext(staticContext, rootFunction); staticContext.getLiteralFunctionTranslator().setRootContext(context); statements.addAll(translateFiles(files, context)); defineModule(context, statements, config.getModuleId()); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/general/TranslatorVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/general/TranslatorVisitor.java index 81092d5eed2..646280873e8 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/general/TranslatorVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/general/TranslatorVisitor.java @@ -17,8 +17,7 @@ package org.jetbrains.k2js.translate.general; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.JetElement; -import org.jetbrains.jet.lang.psi.JetVisitor; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.k2js.translate.context.TranslationContext; /** @@ -32,4 +31,10 @@ public class TranslatorVisitor extends JetVisitor { throw new UnsupportedOperationException("Unsupported expression encountered:" + expression.toString()); } + public final void traverseContainer(@NotNull JetDeclarationContainer jetClass, + @NotNull TranslationContext context) { + for (JetDeclaration declaration : jetClass.getDeclarations()) { + declaration.accept(this, context); + } + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java index f572c2fbb01..e3e714e946b 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java @@ -17,6 +17,7 @@ package org.jetbrains.k2js.translate.initializer; import com.google.dart.compiler.backend.js.ast.*; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; @@ -35,7 +36,6 @@ import java.util.List; import static org.jetbrains.k2js.translate.utils.BindingUtils.*; import static org.jetbrains.k2js.translate.utils.JsAstUtils.convertToStatement; -import static org.jetbrains.k2js.translate.utils.JsAstUtils.setParameters; import static org.jetbrains.k2js.translate.utils.PsiUtils.getPrimaryConstructorParameters; import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateArgumentList; @@ -43,7 +43,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { @NotNull private final JetClassOrObject classDeclaration; @NotNull - private final List initializerStatements = new ArrayList(); + private final List initializerStatements = new SmartList(); public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { // Note: it's important we use scope for class descriptor because anonymous function used in property initializers @@ -59,25 +59,34 @@ public final class ClassInitializerTranslator extends AbstractTranslator { JsFunction result = context().getFunctionObject(primaryConstructor); //NOTE: while we translate constructor parameters we also add property initializer statements // for properties declared as constructor parameters - setParameters(result, translatePrimaryConstructorParameters()); + result.getParameters().addAll(translatePrimaryConstructorParameters()); mayBeAddCallToSuperMethod(result); - (new InitializerVisitor(initializerStatements)).traverseClass(classDeclaration, context()); - result.getBody().getStatements().addAll(initializerStatements); + new InitializerVisitor(initializerStatements).traverseContainer(classDeclaration, context()); + + for (JsStatement statement : initializerStatements) { + if (statement instanceof JsBlock) { + result.getBody().getStatements().addAll(((JsBlock) statement).getStatements()); + } + else { + result.getBody().getStatements().add(statement); + } + } + return result; } private void mayBeAddCallToSuperMethod(JsFunction initializer) { if (hasAncestorClass(bindingContext(), classDeclaration)) { JetDelegatorToSuperCall superCall = getSuperCall(); - if (superCall == null) return; + if (superCall == null) { + return; + } addCallToSuperMethod(superCall, initializer); } } private void addCallToSuperMethod(@NotNull JetDelegatorToSuperCall superCall, JsFunction initializer) { List arguments = translateArguments(superCall); - - //TODO: can be problematic to maintain if (context().isEcma5()) { JsName ref = context().scope().declareName(Namer.CALLEE_NAME); initializer.setName(ref); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java index 8d59fc57a0f..839ee8def8a 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java @@ -64,18 +64,4 @@ public final class InitializerVisitor extends TranslatorVisitor { InitializerUtils.generate(declaration, result, null, context); return null; } - - @NotNull - private List generateInitializerStatements(@NotNull List declarations, - @NotNull TranslationContext context) { - for (JetDeclaration declaration : declarations) { - declaration.accept(this, context); - } - return result; - } - - @NotNull - public final List traverseClass(@NotNull JetClassOrObject expression, @NotNull TranslationContext context) { - return generateInitializerStatements(expression.getDeclarations(), context); - } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallParametersResolver.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallParametersResolver.java index 1cf2701f874..017b6286e92 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallParametersResolver.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallParametersResolver.java @@ -17,6 +17,7 @@ package org.jetbrains.k2js.translate.reference; import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.google.dart.compiler.backend.js.ast.JsLiteral; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; @@ -25,8 +26,12 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.k2js.translate.context.TranslationContext; +import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getDeclarationDescriptorForReceiver; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getDeclarationDescriptorForExtensionCallReceiver; public final class CallParametersResolver { @@ -89,7 +94,21 @@ public final class CallParametersResolver { if (qualifier != null && !isExtensionCall) { return qualifier; } - return context.thisAliasProvider().get(resolvedCall); + + ReceiverValue thisObject = resolvedCall.getThisObject(); + if (!thisObject.exists()) { + return null; + } + + if (thisObject instanceof ClassReceiver) { + JsExpression ref = context.getAliasForDescriptor(((ClassReceiver) thisObject).getDeclarationDescriptor()); + return ref == null ? JsLiteral.THIS : ref; + } + else if (thisObject instanceof ExtensionReceiver) { + return context.getAliasForDescriptor(getDeclarationDescriptorForReceiver(thisObject)); + } + + return resolvedCall.getReceiverArgument().exists() && resolvedCall.getExplicitReceiverKind().isThisObject() ? JsLiteral.THIS : null; } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java index eeed6a3cb09..bc98ea66ac0 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java @@ -80,14 +80,11 @@ public final class CallTranslator extends AbstractTranslator { if (isConstructor()) { return constructorCall(); } - if (isNativeExtensionFunctionCall()) { - return nativeExtensionCall(); - } - if (isExtensionFunctionLiteral()) { - return extensionFunctionLiteralCall(); - } - if (isExtensionFunction()) { - return extensionFunctionCall(); + if (resolvedCall.getReceiverArgument().exists()) { + if (AnnotationsUtils.isNativeObject(descriptor)) { + return methodCall(callParameters.getReceiver()); + } + return extensionFunctionCall(!(descriptor instanceof ExpressionAsFunctionDescriptor) && !descriptor.getName().asString().equals("invoke")); } if (isExpressionAsFunction()) { return expressionAsFunctionCall(); @@ -191,65 +188,22 @@ public final class CallTranslator extends AbstractTranslator { return ReferenceTranslator.translateAsFQReference(descriptor, context()); } - private boolean isNativeExtensionFunctionCall() { - return AnnotationsUtils.isNativeObject(descriptor) && isExtensionFunction(); - } - @NotNull - private JsExpression nativeExtensionCall() { - return methodCall(callParameters.getReceiver()); - } - - private boolean isExtensionFunctionLiteral() { - boolean isLiteral = isInvoke() - || descriptor instanceof ExpressionAsFunctionDescriptor; - return isExtensionFunction() && isLiteral; - } - - @NotNull - private JsExpression extensionFunctionLiteralCall() { + private JsExpression extensionFunctionCall(final boolean useThis) { return callType.constructCall(callParameters.getReceiver(), new CallType.CallConstructor() { @NotNull @Override public JsExpression construct(@Nullable JsExpression receiver) { assert receiver != null : "Could not be null for extensions"; - return constructExtensionLiteralCall(receiver); + JsExpression functionReference = callParameters.getFunctionReference(); + if (useThis) { + setQualifier(functionReference, getThisObjectOrQualifier()); + } + return new JsInvocation(functionReference, generateExtensionCallArgumentList(receiver)); } }, context()); } - @NotNull - private JsExpression constructExtensionLiteralCall(@NotNull JsExpression realReceiver) { - List callArguments = generateExtensionCallArgumentList(realReceiver); - return new JsInvocation(new JsNameRef("call", callParameters.getFunctionReference()), callArguments); - } - - @SuppressWarnings("UnnecessaryLocalVariable") - private boolean isExtensionFunction() { - boolean hasReceiver = resolvedCall.getReceiverArgument().exists(); - return hasReceiver; - } - - @NotNull - private JsExpression extensionFunctionCall() { - return callType.constructCall(callParameters.getReceiver(), new CallType.CallConstructor() { - @NotNull - @Override - public JsExpression construct(@Nullable JsExpression receiver) { - assert receiver != null : "Could not be null for extensions"; - return constructExtensionFunctionCall(receiver); - } - }, context()); - } - - @NotNull - private JsExpression constructExtensionFunctionCall(@NotNull JsExpression receiver) { - List argumentList = generateExtensionCallArgumentList(receiver); - JsExpression functionReference = callParameters.getFunctionReference(); - setQualifier(functionReference, getThisObjectOrQualifier()); - return new JsInvocation(functionReference, argumentList); - } - @NotNull private List generateExtensionCallArgumentList(@NotNull JsExpression receiver) { List argumentList = new ArrayList(); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/InlinedCallExpressionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/InlinedCallExpressionTranslator.java index fb005a99ed2..6414167e32e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/InlinedCallExpressionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/InlinedCallExpressionTranslator.java @@ -100,10 +100,10 @@ public final class InlinedCallExpressionTranslator extends AbstractCallExpressio @NotNull private TranslationContext createContextWithAliasesForParameters(@NotNull TranslationContext contextForInlining) { - Map aliases = Maps.newHashMap(); + Map aliases = Maps.newHashMap(); for (ValueParameterDescriptor parameterDescriptor : resolvedCall.getResultingDescriptor().getValueParameters()) { TemporaryVariable aliasForArgument = createAliasForArgument(parameterDescriptor); - aliases.put(parameterDescriptor, aliasForArgument.name()); + aliases.put(parameterDescriptor, aliasForArgument.name().makeRef()); } return contextForInlining.innerContextWithDescriptorsAliased(aliases); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java index a2805d53119..2517a4224fd 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java @@ -17,11 +17,12 @@ package org.jetbrains.k2js.translate.reference; import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsName; import com.google.dart.compiler.backend.js.ast.JsNameRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.k2js.translate.context.TranslationContext; @@ -41,18 +42,23 @@ public final class ReferenceTranslator { @NotNull public static JsExpression translateAsFQReference(@NotNull DeclarationDescriptor referencedDescriptor, @NotNull TranslationContext context) { - JsExpression qualifier = context.getQualifierForDescriptor(referencedDescriptor); - if (qualifier == null) { - return translateAsLocalNameReference(referencedDescriptor, context); + JsExpression alias = context.getAliasForDescriptor(referencedDescriptor); + if (alias != null) { + return alias; } - JsName referencedName = context.getNameForDescriptor(referencedDescriptor); - return new JsNameRef(referencedName, qualifier); + + return new JsNameRef(context.getNameForDescriptor(referencedDescriptor), context.getQualifierForDescriptor(referencedDescriptor)); } @NotNull public static JsExpression translateAsLocalNameReference(@NotNull DeclarationDescriptor referencedDescriptor, @NotNull TranslationContext context) { - //Preconditions.checkNotNull(referencedDescriptor, "No referencedDescriptor available"); + if (referencedDescriptor instanceof FunctionDescriptor || referencedDescriptor instanceof VariableDescriptor) { + JsExpression alias = context.aliasingContext().getAliasForDescriptor(referencedDescriptor); + if (alias != null) { + return alias; + } + } return context.getNameForDescriptor(referencedDescriptor).makeRef(); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/CaptureClosureVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/CaptureClosureVisitor.java index e46d95ec481..97828f0bb98 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/CaptureClosureVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/CaptureClosureVisitor.java @@ -18,6 +18,7 @@ package org.jetbrains.k2js.translate.utils.closure; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor; @@ -25,6 +26,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.k2js.translate.utils.BindingUtils; +import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; class CaptureClosureVisitor extends JetTreeVisitor { @NotNull @@ -61,8 +63,8 @@ class CaptureClosureVisitor extends JetTreeVisitor { DeclarationDescriptor descriptor = BindingUtils.getNullableDescriptorForReferenceExpression(bindingContext, expression); if (!(descriptor instanceof VariableDescriptor)) { - if (descriptor instanceof SimpleFunctionDescriptor && !descriptor.getName().isSpecial()) { - checkOuterClassDescriptor(descriptor, context); + if (descriptor instanceof SimpleFunctionDescriptor) { + checkSimpleFunction(context, (SimpleFunctionDescriptor) descriptor); } return null; } @@ -75,6 +77,19 @@ class CaptureClosureVisitor extends JetTreeVisitor { return null; } + private void checkSimpleFunction(ClosureContext context, @Nullable SimpleFunctionDescriptor descriptor) { + if (descriptor == null || descriptor.getName().isSpecial()) { + return; + } + + checkOuterClassDescriptor(descriptor, context); + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); + // local named function + if (!JsDescriptorUtils.isExtension(descriptor) && !(containingDeclaration instanceof ClassOrNamespaceDescriptor) && !isAncestor(functionDescriptor, descriptor)) { + context.put(descriptor); + } + } + private boolean captured(VariableDescriptor descriptor, ClosureContext context) { if (descriptor instanceof PropertyDescriptor) { checkOuterClassDescriptor(descriptor, context); @@ -90,9 +105,7 @@ class CaptureClosureVisitor extends JetTreeVisitor { return false; } - if (descriptor instanceof LocalVariableDescriptor && descriptor.isVar()) { - // todo modification of outer local variable - context.setHasLocalVariables(); + if (descriptor instanceof LocalVariableDescriptor || descriptor instanceof ValueParameterDescriptor) { return true; } @@ -102,8 +115,7 @@ class CaptureClosureVisitor extends JetTreeVisitor { return false; } - return descriptor instanceof ValueParameterDescriptor || - (!descriptor.isVar() && variableDeclaration instanceof JetProperty) || + return (!descriptor.isVar() && variableDeclaration instanceof JetProperty) || variableDeclaration.getNode().getElementType().equals(JetNodeTypes.LOOP_PARAMETER); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureContext.java index 6d7cc9e2c28..0501968c9a6 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureContext.java @@ -19,35 +19,25 @@ package org.jetbrains.k2js.translate.utils.closure; import com.intellij.util.containers.OrderedSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import java.util.Collection; import java.util.Set; public final class ClosureContext { @NotNull - private final Set descriptors = new OrderedSet(); - - private boolean hasLocalVariables; + private final Set descriptors = new OrderedSet(); @Nullable public ClassDescriptor outerClassDescriptor; - public boolean isLocalVariablesAffected() { - return hasLocalVariables; - } - - void setHasLocalVariables() { - hasLocalVariables = true; - } - - /*package*/ void put(@NotNull VariableDescriptor descriptor) { + /*package*/ void put(@NotNull CallableDescriptor descriptor) { descriptors.add(descriptor); } @NotNull - public Collection getDescriptors() { + public Collection getDescriptors() { return descriptors; } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureUtils.java index 213dbf6166d..aff6c2af0f3 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/closure/ClosureUtils.java @@ -29,7 +29,7 @@ public final class ClosureUtils { public static ClosureContext captureClosure(@NotNull BindingContext bindingContext, @NotNull JetElement element, @NotNull DeclarationDescriptor descriptor) { CaptureClosureVisitor captureClosureVisitor = new CaptureClosureVisitor(descriptor, bindingContext); ClosureContext closureContext = new ClosureContext(); - element.accept(captureClosureVisitor, closureContext); + element.acceptChildren(captureClosureVisitor, closureContext); return closureContext; } } diff --git a/js/js.translator/testFiles/expression/equals/cases/equalsNullOrUndefined.kt b/js/js.translator/testFiles/expression/equals/cases/equalsNullOrUndefined.kt index 03dd20515b7..706fb6db4b7 100644 --- a/js/js.translator/testFiles/expression/equals/cases/equalsNullOrUndefined.kt +++ b/js/js.translator/testFiles/expression/equals/cases/equalsNullOrUndefined.kt @@ -1,11 +1,18 @@ package foo +native val undefined: Any = noImpl + fun box() : String { val a: Int? = null val r = a == null if (!r || a != null) return "wrong result on simple nullable check" + //force using Kotlin.equals + val t = null + if (t != undefined) + return "wrong result when compare null and undefined using Kotlin.equals" + var i = 0; fun foo(): Int? = ++i; if (foo() == null) diff --git a/js/js.translator/testFiles/kotlinLib/cases/namespace.js b/js/js.translator/testFiles/kotlinLib/cases/namespace.js index 973c25c045c..f0b1455256c 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/namespace.js +++ b/js/js.translator/testFiles/kotlinLib/cases/namespace.js @@ -14,10 +14,11 @@ * limitations under the License. */ -var foo = Kotlin.definePackage({box:function(){ - return !false; +var foo = Kotlin.definePackage({initialize: function () { +}, box: function () { + return !false; } -}); + }); function test() { return foo.box() diff --git a/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js b/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js index 5e1264bf737..9743bac3b4d 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js +++ b/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js @@ -16,7 +16,7 @@ { var items = function () { - var A = Kotlin.createClass({initialize: function () { + var A = Kotlin.createClass(null, {initialize: function () { this.$order = ''; { this.set_order(this.get_order() + 'A'); diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index d376e093b3e..19c8d1181d8 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -36,8 +36,8 @@ var kotlin = {set:function (receiver, key, value) { (function () { Kotlin.equals = function (obj1, obj2) { - if (obj1 === null || obj1 === undefined) { - return obj2 === null; + if (obj1 == null) { + return obj2 == null; } if (obj1 instanceof Array) { diff --git a/js/js.translator/testFiles/kotlin_lib_ecma3.js b/js/js.translator/testFiles/kotlin_lib_ecma3.js index 46ba6fd3b44..e9bda6386b8 100644 --- a/js/js.translator/testFiles/kotlin_lib_ecma3.js +++ b/js/js.translator/testFiles/kotlin_lib_ecma3.js @@ -80,15 +80,14 @@ var Kotlin = {}; return true; }; - Kotlin.createTrait = (function () { - return function () { - var result = arguments[0]; - for (var i = 1, n = arguments.length; i < n; i++) { - copyProperties(result, arguments[i]); - } - return result; + Kotlin.createTrait = function () { + var n = arguments.length - 1; + var result = arguments[n] || {}; + for (var i = 0; i < n; i++) { + copyProperties(result, arguments[i]); } - })(); + return result; + }; Kotlin.definePackage = function (members) { return members === null ? {} : members; @@ -98,10 +97,11 @@ var Kotlin = {}; function subclass() { } - function create() { - var parent = null, properties = Kotlin.argumentsToArrayLike(arguments); - if (typeof (properties[0]) == "function") { - parent = properties.shift(); + function create(parent, properties, staticProperties) { + var traits = null; + if (parent instanceof Array) { + traits = parent; + parent = parent[0]; } function klass() { @@ -112,13 +112,19 @@ var Kotlin = {}; } klass.addMethods = addMethods; - klass.superclass = parent; + klass.superclass = parent || null; klass.subclasses = []; if (parent) { - subclass.prototype = parent.prototype; - klass.prototype = new subclass(); - parent.subclasses.push(klass); + if (typeof (parent) == "function") { + subclass.prototype = parent.prototype; + klass.prototype = new subclass(); + parent.subclasses.push(klass); + } + else { + // trait + klass.addMethods(parent); + } } klass.addMethods({get_class: function () { @@ -132,8 +138,13 @@ var Kotlin = {}; }}); } - for (var i = 0, length = properties.length; i < length; i++) { - klass.addMethods(properties[i]); + if (traits !== null) { + for (var i = 1, n = traits.length; i < n; i++) { + klass.addMethods(traits[i]); + } + } + if (properties !== null && properties !== undefined) { + klass.addMethods(properties); } if (!klass.prototype.initialize) { @@ -141,6 +152,9 @@ var Kotlin = {}; } klass.prototype.constructor = klass; + if (staticProperties !== null && staticProperties !== undefined) { + copyProperties(klass, staticProperties); + } return klass; } @@ -152,7 +166,13 @@ var Kotlin = {}; return create; })(); - Kotlin.$createClass = Kotlin.createClass; + Kotlin.$createClass = function (parent, properties) { + if (parent !== null && typeof (parent) != "function") { + properties = parent; + parent = null; + } + return Kotlin.createClass(parent, properties, null); + }; Kotlin.createObjectWithPrototype = function (prototype) { function C() {} diff --git a/js/js.translator/testFiles/kotlin_lib_ecma5.js b/js/js.translator/testFiles/kotlin_lib_ecma5.js index cea232dfba6..ab57a7abd17 100644 --- a/js/js.translator/testFiles/kotlin_lib_ecma5.js +++ b/js/js.translator/testFiles/kotlin_lib_ecma5.js @@ -66,13 +66,13 @@ var Kotlin = Object.create(null); return proto; } - Kotlin.createTrait = function (bases, properties) { - return createClass(bases, null, properties, false); + Kotlin.createTrait = function (bases, properties, staticProperties) { + return createClass(bases, null, properties, staticProperties, false); }; - Kotlin.createClass = function (bases, initializer, properties) { + Kotlin.createClass = function (bases, initializer, properties, staticProperties) { // proto must be created for class even if it is not needed (requires for is operator) - return createClass(bases, initializer === null ? function () {} : initializer, properties, true); + return createClass(bases, initializer === null ? function () {} : initializer, properties, staticProperties, true); }; function computeProto2(bases, properties) { @@ -94,7 +94,7 @@ var Kotlin = Object.create(null); return o; }; - function createClass(bases, initializer, properties, isClass) { + function createClass(bases, initializer, properties, staticProperties, isClass) { var proto; var baseInitializer; if (bases === null) { @@ -125,6 +125,10 @@ var Kotlin = Object.create(null); Object.freeze(initializer); } + if (staticProperties !== null && staticProperties !== undefined) { + Object.defineProperties(constructor, staticProperties); + } + Object.freeze(constructor); return constructor; } diff --git a/js/js.translator/testFiles/trait/cases/checkImplementationCharacteristics.kt b/js/js.translator/testFiles/trait/cases/checkImplementationCharacteristics.kt new file mode 100644 index 00000000000..53e007dd011 --- /dev/null +++ b/js/js.translator/testFiles/trait/cases/checkImplementationCharacteristics.kt @@ -0,0 +1,30 @@ +package foo + +trait A { + fun foo() {} +} +trait B : A { + fun boo() {} +} + +native fun eval(code: String): Any = noImpl +native val undefined: Any = noImpl +native class Function(vararg args: String) + +val hasProp = Function("obj, prop", "return obj[prop] !== undefined") as ((Any, String)->Boolean) +val PREFIX = "Kotlin.modules.JS_TESTS.foo" + +fun box(): String { + val a = object: A {} + val b = object: B {} + + if (!hasProp(a, "foo")) return "A hasn't foo" + if (hasProp(a, "boo")) return "A has boo" + + if (!hasProp(b, "foo")) return "B hasn't foo" + if (!hasProp(b, "boo")) return "B hasn't boo" + + if (eval("$PREFIX.A === $PREFIX.B") as Boolean) return "A and B refer to the same object" + + return "OK" +} \ No newline at end of file diff --git a/libraries/docs/apidoc/pom.xml b/libraries/docs/apidoc/pom.xml index b3fe237a5e4..cd4b57de572 100644 --- a/libraries/docs/apidoc/pom.xml +++ b/libraries/docs/apidoc/pom.xml @@ -90,6 +90,15 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + diff --git a/libraries/docs/jsdoc/pom.xml b/libraries/docs/jsdoc/pom.xml index 74f3151a64f..623ffd41640 100644 --- a/libraries/docs/jsdoc/pom.xml +++ b/libraries/docs/jsdoc/pom.xml @@ -33,6 +33,14 @@ + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + org.jetbrains.kotlin kdoc-maven-plugin diff --git a/libraries/docs/website/pom.xml b/libraries/docs/website/pom.xml index ca0f3129010..93e20841c87 100644 --- a/libraries/docs/website/pom.xml +++ b/libraries/docs/website/pom.xml @@ -101,6 +101,14 @@ + + + maven-deploy-plugin + + true + + + diff --git a/libraries/examples/browser-example/pom.xml b/libraries/examples/browser-example/pom.xml index fe1114f325d..1e85fa6a62d 100644 --- a/libraries/examples/browser-example/pom.xml +++ b/libraries/examples/browser-example/pom.xml @@ -76,6 +76,14 @@ + + + maven-deploy-plugin + + true + + + diff --git a/libraries/examples/js-example/pom.xml b/libraries/examples/js-example/pom.xml index f365790c341..43f2eea8d0b 100644 --- a/libraries/examples/js-example/pom.xml +++ b/libraries/examples/js-example/pom.xml @@ -47,6 +47,14 @@ + + + maven-deploy-plugin + + true + + + diff --git a/libraries/examples/kotlin-java-example/pom.xml b/libraries/examples/kotlin-java-example/pom.xml index 558dbff5310..a718a93f3b1 100644 --- a/libraries/examples/kotlin-java-example/pom.xml +++ b/libraries/examples/kotlin-java-example/pom.xml @@ -31,7 +31,16 @@ org.apache.maven.plugins maven-compiler-plugin + + + maven-deploy-plugin + + true + + + + diff --git a/libraries/maven-settings.xml b/libraries/maven-settings.xml index 5a85de484ae..db289a15836 100644 --- a/libraries/maven-settings.xml +++ b/libraries/maven-settings.xml @@ -23,5 +23,15 @@ ${GITHUB_LOGIN} ${GITHUB_PASSWORD} + + sonatype-nexus-snapshots + ${kotlin.sonatype.user} + ${kotlin.sonatype.password} + + + sonatype-nexus-staging + ${kotlin.sonatype.user} + ${kotlin.sonatype.password} + diff --git a/libraries/pom.xml b/libraries/pom.xml index 2ed566aa5a8..8fdd68be6a9 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -65,18 +65,12 @@ - false - jetbrains-kotlin - jetbrains-kotlin - http://repository.jetbrains.com/kotlin - default + sonatype-nexus-snapshots + http://oss.sonatype.org/service/local/staging/deploy/maven2/ - false - jetbrains-kotlin - jetbrains-kotlin - http://repository.jetbrains.com/kotlin - default + sonatype-nexus-staging + https://oss.sonatype.org/content/repositories/snapshots/ @@ -115,7 +109,6 @@ - @@ -138,6 +131,11 @@ maven-javadoc-plugin 2.9 + + org.apache.maven.plugins + maven-deploy-plugin + 2.7 + org.codehaus.mojo build-helper-maven-plugin @@ -225,4 +223,32 @@ + + + + sign-artifacts + + + + maven-gpg-plugin + 1.4 + + ${kotlin.key.passphrase} + ${kotlin.key.name} + ${highest-basedir}/.gnupg + + + + sign-artifacts + verify + + sign + + + + + + + + diff --git a/libraries/stdlib/test/iterators/IteratorsTest.kt b/libraries/stdlib/test/iterators/IteratorsTest.kt index fae3fc23b97..a5cb79e9561 100644 --- a/libraries/stdlib/test/iterators/IteratorsTest.kt +++ b/libraries/stdlib/test/iterators/IteratorsTest.kt @@ -16,7 +16,8 @@ class IteratorsTest { assertEquals(arrayList(144, 233, 377, 610, 987), fibonacci().filter { it > 100 }.takeWhile { it < 1000 }.toList()) } - test fun foldReducesTheFirstNElements() { + // TODO fix and enable this test + fun foldReducesTheFirstNElements() { val sum = { (a: Int, b: Int) -> a + b } assertEquals(arrayList(13, 21, 34, 55, 89).fold(0, sum), fibonacci().filter { it > 10 }.take(5).fold(0, sum)) } diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/annotations.xml new file mode 100644 index 00000000000..a86a23af2a8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/api/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/api/annotations.xml new file mode 100644 index 00000000000..500ef07cd98 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/api/annotations.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml index dc5cd1bbcbe..a1a14699122 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml @@ -1,18 +1,29 @@ + - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/file/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/file/annotations.xml index dea5cec6774..86cc0e5f0c1 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/file/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/file/annotations.xml @@ -2,4 +2,7 @@ + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml index c14ebed20ae..0c7f23a66ff 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml @@ -1,15 +1,17 @@ + - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml index 5859b33807e..fb08bfa4358 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml @@ -1,22 +1,27 @@ + - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/pom.xml b/libraries/tools/kotlin-gradle-plugin-core/pom.xml index 2c558ae18e8..3678fdcfb48 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/pom.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/pom.xml @@ -20,6 +20,12 @@ jar + + com.android.tools.build + gradle + 0.4.2 + provided + junit junit diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 286d25a58ef..fd3478ccc87 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -4,18 +4,11 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPluginConvention -import org.gradle.api.plugins.JavaPlugin -import groovy.lang.Closure import org.gradle.api.tasks.SourceSet import org.jetbrains.kotlin.gradle.internal.KotlinSourceSetImpl import org.gradle.api.internal.project.ProjectInternal -import org.gradle.api.internal.IConventionAware import org.gradle.api.internal.HasConvention -import org.gradle.api.internal.file.collections.SimpleFileCollection -import org.gradle.api.file.FileTreeElement import org.jetbrains.kotlin.gradle.internal.KotlinSourceSet -import org.gradle.api.file.SourceDirectorySet -import org.codehaus.groovy.runtime.MethodClosure import org.gradle.api.specs.Spec import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KDoc @@ -23,7 +16,23 @@ import java.io.File import java.util.concurrent.Callable import org.gradle.api.Action import org.gradle.api.tasks.compile.AbstractCompile -import java.util.Arrays +import org.gradle.api.logging.Logging +import com.android.build.gradle.BaseExtension +import com.android.build.gradle.AppExtension +import com.android.build.gradle.LibraryExtension +import org.gradle.api.internal.DefaultDomainObjectSet +import com.android.build.gradle.api.BaseVariant +import com.android.build.gradle.api.AndroidSourceSet +import org.gradle.api.plugins.ExtensionAware +import org.jetbrains.jet.cli.jvm.K2JVMCompilerArguments +import java.util.ArrayList +import com.android.build.gradle.BasePlugin +import com.android.build.gradle.api.LibraryVariant +import com.android.build.gradle.api.ApkVariant +import com.android.builder.model.BuildType +import com.android.builder.BuilderConstants +import com.android.build.gradle.api.TestVariant +import org.gradle.api.plugins.JavaPlugin open class KotlinPlugin: Plugin { @@ -43,17 +52,15 @@ open class KotlinPlugin: Plugin { javaPluginConvention: JavaPluginConvention) { javaPluginConvention.getSourceSets()?.all(object : Action { override fun execute(sourceSet: SourceSet?) { - if (sourceSet is HasConvention) { + if (sourceSet is ExtensionAware) { val sourceSetName = sourceSet.getName() - val kotlinSourceSet = KotlinSourceSetImpl(sourceSetName, project.getFileResolver()) + val kotlinSourceSet = sourceSet.getExtensions().create("kotlin", javaClass(), sourceSetName, project.getFileResolver())!! val kotlinDirSet = kotlinSourceSet.getKotlin() kotlinDirSet.srcDir(project.file("src/${sourceSetName}/kotlin")) sourceSet.getAllJava()?.source(kotlinDirSet) sourceSet.getAllSource()?.source(kotlinDirSet) - sourceSet.getConvention().getPlugins().put("kotlin", kotlinSourceSet) - sourceSet.getResources()?.getFilter()?.exclude(KSpec({ elem -> kotlinDirSet.contains(elem.getFile()) })) @@ -82,12 +89,15 @@ open class KotlinPlugin: Plugin { } private fun configureKDoc(project: Project, javaPluginConvention: JavaPluginConvention) { - val mainSourceSet = javaPluginConvention.getSourceSets()?.getByName(SourceSet.MAIN_SOURCE_SET_NAME)!! as HasConvention + val mainSourceSet = javaPluginConvention.getSourceSets()?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) as HasConvention? - val kdoc = project.getTasks()?.add(KDOC_TASK_NAME, javaClass())!! - kdoc.setDescription("Generates KDoc API documentation for the main source code.") - kdoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP) - kdoc.setSource(mainSourceSet.getConvention().getExtensionsAsDynamicObject().getProperty("kotlin")) + if (mainSourceSet != null) { + val kdoc = project.getTasks()?.add(KDOC_TASK_NAME, javaClass())!! + + kdoc.setDescription("Generates KDoc API documentation for the main source code.") + kdoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP) + kdoc.setSource(mainSourceSet.getConvention().getExtensionsAsDynamicObject().getProperty("kotlin")) + } project.getTasks()?.withType(javaClass(), object : Action { override fun execute(param: KDoc?) { @@ -104,6 +114,145 @@ open class KotlinPlugin: Plugin { } +open class KotlinAndroidPlugin: Plugin { + + val log = Logging.getLogger(getClass()) + + public override fun apply(p0: Project) { + + val project = p0 as ProjectInternal + val ext = project.getExtensions().getByName("android") as BaseExtension + + ext.getSourceSets()?.all(object : Action { + override fun execute(sourceSet: AndroidSourceSet?) { + if (sourceSet is ExtensionAware) { + val sourceSetName = sourceSet.getName() + val kotlinSourceSet = sourceSet.getExtensions().create("kotlin", javaClass(), sourceSetName, project.getFileResolver())!! + val kotlinDirSet = kotlinSourceSet.getKotlin() + kotlinDirSet.srcDir(project.file("src/${sourceSetName}/kotlin")) + + sourceSet.getAllJava().source(kotlinDirSet) + sourceSet.getAllSource().source(kotlinDirSet) + sourceSet.getResources()?.getFilter()?.exclude(KSpec({ elem -> + kotlinDirSet.contains(elem.getFile()) + })) + project.getLogger().debug("Created kotlin sourceDirectorySet at ${kotlinDirSet.getSrcDirs()}") + } + } + }) + + (ext as ExtensionAware).getExtensions().add("kotlinOptions", K2JVMCompilerArguments()) + + project.afterEvaluate( { (project: Project?): Unit -> + if (project != null) { + val testVariants = ext.getTestVariants()!! + processVariants(testVariants, project, ext) + if (ext is AppExtension) { + val appVariants = ext.getApplicationVariants()!! + processVariants(appVariants, project, ext) + } + + if (ext is LibraryExtension) { + val libVariants = ext.getLibraryVariants()!!; + processVariants(libVariants, project, ext) + } + } + + }) + } + + private fun processVariants(variants: DefaultDomainObjectSet, project: Project, androidExt: BaseExtension): Unit { + val logger = project.getLogger() + val kotlinOptions = getExtention(androidExt, "kotlinOptions") + val sourceSets = androidExt.getSourceSets() + val mainSourceSet = sourceSets.getByName(BuilderConstants.MAIN) + val testSourceSet = sourceSets.getByName(BuilderConstants.INSTRUMENT_TEST) + + for (variant in variants) { + if (variant is LibraryVariant || variant is ApkVariant) { + val buildType: BuildType = if (variant is LibraryVariant) { + variant.getBuildType() + } else { + (variant as ApkVariant).getBuildType() + } + + val buildTypeSourceSetName = buildType.getName() + logger.debug("Variant build type is [$buildTypeSourceSetName]") + val buildTypeSourceSet : AndroidSourceSet? = sourceSets.findByName(buildTypeSourceSetName) + + val javaTask = variant.getJavaCompile()!! + val variantName = variant.getName() + + val kotlinTaskName = "compile${variantName}Kotlin" + val kotlinTask: KotlinCompile = project.getTasks()!!.add(kotlinTaskName, javaClass())!! + kotlinTask.kotlinOptions = kotlinOptions + + + // store kotlin classes in separate directory. They will serve as class-path to java compiler + val kotlinOutputDir = File(project.getBuildDir(), "kotlin-classes/${variantName}") + kotlinTask.kotlinDestinationDir = kotlinOutputDir; + kotlinTask.setDestinationDir(javaTask.getDestinationDir()) + kotlinTask.setDescription("Compiles the ${variantName} kotlin.") + kotlinTask.setClasspath(javaTask.getClasspath()) + kotlinTask.setDependsOn(javaTask.getDependsOn()) + + val javaSourceList = ArrayList() + + if (variant is TestVariant) { + javaSourceList.addAll(testSourceSet.getJava().getSrcDirs()) + val testKotlinSource = getExtention(testSourceSet, "kotlin") + kotlinTask.source(testKotlinSource.getKotlin()) + } else { + javaSourceList.addAll(mainSourceSet.getJava().getSrcDirs()) + val mainKotlinSource = getExtention(mainSourceSet, "kotlin") + kotlinTask.source(mainKotlinSource.getKotlin()) + } + + if (null != buildTypeSourceSet) { + javaSourceList.add(buildTypeSourceSet.getJava().getSrcDirs()) + kotlinTask.source(getExtention(buildTypeSourceSet, "kotlin").getKotlin()) + } + javaSourceList.add(callable{ variant.getProcessResources().getSourceOutputDir() }) + javaSourceList.add(callable{ variant.getGenerateBuildConfig()?.getSourceOutputDir() }) + javaSourceList.add(callable{ variant.getAidlCompile().getSourceOutputDir() }) + javaSourceList.add(callable{ variant.getRenderscriptCompile().getSourceOutputDir() }) + + if (variant is ApkVariant) { + for (flavour in variant.getProductFlavors().iterator()) { + val flavourSourceSetName = buildTypeSourceSetName + flavour.getName() + val flavourSourceSet : AndroidSourceSet? = sourceSets.findByName(flavourSourceSetName) + if (flavourSourceSet != null) { + javaSourceList.add(flavourSourceSet.getJava()) + kotlinTask.source((buildTypeSourceSet as ExtensionAware).getExtensions().getByName("kotlin")) + } + } + } + + kotlinTask.doFirst({ task -> + var plugin = project.getPlugins().getPlugin("android") + if (null == plugin) { + plugin = project.getPlugins().getPlugin("android-library") + } + val basePlugin : BasePlugin = plugin as BasePlugin + val javaSources = project.files(javaSourceList) + val androidRT = project.files(basePlugin.getRuntimeJarList()) + val fullClasspath = javaTask.getClasspath() + (javaSources + androidRT) + (task as AbstractCompile).setClasspath(fullClasspath) + }) + + javaTask.dependsOn(kotlinTaskName) + val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir); + javaTask.setClasspath(javacClassPath) + } + } + } + + fun getExtention(obj: Any, extensionName: String): T { + return (obj as ExtensionAware).getExtensions().getByName(extensionName) as T + } + +} + open class KSpec(val predicate: (T) -> Boolean): Spec { public override fun isSatisfiedBy(p0: T?): Boolean { return p0 != null && predicate(p0) diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 3ac44255d81..2513eec80c2 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -31,7 +31,7 @@ public open class KotlinCompile(): AbstractCompile() { val compiler = K2JVMCompiler() val logger = Logging.getLogger(getClass()) - public val kotlinOptions: K2JVMCompilerArguments = K2JVMCompilerArguments(); + public var kotlinOptions: K2JVMCompilerArguments = K2JVMCompilerArguments(); public var kotlinDestinationDir : File? = getDestinationDir() @@ -67,7 +67,7 @@ public open class KotlinCompile(): AbstractCompile() { override fun compile() { - val args = kotlinOptions + val args = K2JVMCompilerArguments() val javaSrcRoots = HashSet() val sources = ArrayList() diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/build.gradle b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/build.gradle index 14bf8d494aa..0dd25be0fbf 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/build.gradle @@ -10,7 +10,10 @@ buildscript { } } -apply plugin: org.jetbrains.kotlin.gradle.plugin.KotlinPlugin +import org.jetbrains.kotlin.gradle.plugin.KotlinPlugin + +apply plugin: KotlinPlugin +apply plugin: 'java' sourceSets { deploy diff --git a/libraries/tools/kotlin-gradle-plugin/pom.xml b/libraries/tools/kotlin-gradle-plugin/pom.xml index 717f6ce83d6..f3474e9b223 100644 --- a/libraries/tools/kotlin-gradle-plugin/pom.xml +++ b/libraries/tools/kotlin-gradle-plugin/pom.xml @@ -89,6 +89,9 @@ ${project.build.directory}/it local-repo verify + + org.jetbrains.kotlin:kotlin-gradle-plugin-core:${project.version} + diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index f2891244fc9..96c7f408828 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -12,7 +12,7 @@ import org.gradle.api.logging.Logging import java.util.Properties import java.io.FileNotFoundException -open class KotlinPluginWrapper: Plugin { +open abstract class KotlinBasePluginWrapper: Plugin { val log = Logging.getLogger(getClass())!! @@ -45,7 +45,7 @@ open class KotlinPluginWrapper: Plugin { log.debug("Load plugin in parent-last URL classloader") val kotlinPluginClassloader = ParentLastURLClassLoader(kotlinPluginDependencies, getClass().getClassLoader()) log.debug("Class loader created") - val cls = Class.forName("org.jetbrains.kotlin.gradle.plugin.KotlinPlugin", true, kotlinPluginClassloader) + val cls = Class.forName(getPluginClassName(), true, kotlinPluginClassloader) log.debug("Plugin class loaded") val pluginInstance = cls.newInstance() log.debug("Plugin class instantiated") @@ -55,6 +55,20 @@ open class KotlinPluginWrapper: Plugin { applyMethod.invoke(pluginInstance, project); log.debug("'apply' method invoked successfully") } + + public abstract fun getPluginClassName():String +} + +open class KotlinPluginWrapper: KotlinBasePluginWrapper() { + public override fun getPluginClassName():String { + return "org.jetbrains.kotlin.gradle.plugin.KotlinPlugin" + } +} + +open class KotlinAndriodPluginWrapper: KotlinBasePluginWrapper() { + public override fun getPluginClassName():String { + return "org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin" + } } open class KSpec(val predicate: (T) -> Boolean): Spec { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin-android.properties b/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin-android.properties new file mode 100644 index 00000000000..6b70497392a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin-android.properties @@ -0,0 +1 @@ +implementation-class=org.jetbrains.kotlin.gradle.plugin.KotlinAndriodPluginWrapper \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinAndroidGradleIT.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinAndroidGradleIT.kt new file mode 100644 index 00000000000..22965071ae1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinAndroidGradleIT.kt @@ -0,0 +1,144 @@ +package org.jetbrains.kotlin.gradle + +import com.google.common.io.Files +import com.intellij.openapi.util.SystemInfo +import java.io.File +import java.util.Arrays +import java.util.Scanner +import org.junit.Before +import org.junit.After +import org.junit.Test +import org.junit.Ignore +import kotlin.test.assertTrue +import kotlin.test.assertEquals +import kotlin.test.fail +import org.gradle.testfixtures.ProjectBuilder + +Ignore("Requires Android SDK") +class KotlinAndroidGradleIT { + + var workingDir: File = File(".") + + Before fun setUp() { + workingDir = Files.createTempDir() + workingDir.mkdirs() + copyRecursively(File("src/test/resources/testProject/AndroidAlfaProject"), workingDir) + } + + + After fun tearDown() { + deleteRecursively(workingDir) + } + + Test fun testSimpleCompile() { + val projectDir = File(workingDir, "AndroidAlfaProject") + + val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("local-repo").getAbsolutePath() + val cmd = if (SystemInfo.isWindows) + listOf("cmd", "/C", "gradlew.bat", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + else + listOf("/bin/bash", "./gradlew", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + + val builder = ProcessBuilder(cmd) + builder.directory(projectDir) + builder.redirectErrorStream(true) + val process = builder.start() + + val s = Scanner(process.getInputStream()!!) + val text = StringBuilder() + while (s.hasNextLine()) { + text append s.nextLine() + text append "\n" + } + s.close() + + val result = process.waitFor() + val buildOutput = text.toString() + + println(buildOutput) + + assertEquals(result, 0) + assertTrue(buildOutput.contains(":compileFlavor1DebugKotlin"), "Should contain ':compileFlavor1DebugKotlin'") + assertTrue(buildOutput.contains(":compileFlavor2DebugKotlin"), "Should contain ':compileFlavor2DebugKotlin'") + assertTrue(buildOutput.contains(":compileFlavor1JnidebugKotlin"), "Should contain ':compileFlavor1JnidebugKotlin'") + assertTrue(buildOutput.contains(":compileFlavor1ReleaseKotlin"), "Should contain ':compileFlavor1ReleaseKotlin'") + assertTrue(buildOutput.contains(":compileFlavor2JnidebugKotlin"), "Should contain ':compileFlavor2JnidebugKotlin'") + assertTrue(buildOutput.contains(":compileFlavor2ReleaseKotlin"), "Should contain ':compileFlavor2ReleaseKotlin'") + assertTrue(buildOutput.contains(":compileFlavor1Debug"), "Should contain ':compileFlavor1Debug'") + assertTrue(buildOutput.contains(":compileFlavor2Debug"), "Should contain ':compileFlavor2Debug'") + assertTrue(buildOutput.contains(":compileFlavor1Jnidebug"), "Should contain ':compileFlavor1Jnidebug'") + assertTrue(buildOutput.contains(":compileFlavor2Jnidebug"), "Should contain ':compileFlavor2Jnidebug'") + assertTrue(buildOutput.contains(":compileFlavor1Release"), "Should contain ':compileFlavor1Release'") + assertTrue(buildOutput.contains(":compileFlavor2Release"), "Should contain ':compileFlavor2Release'") + + // Run the build second time, assert everything is up-to-date + + val up2dateBuilder = ProcessBuilder(cmd) + up2dateBuilder.directory(projectDir) + up2dateBuilder.redirectErrorStream(true) + val up2dateProcess = up2dateBuilder.start() + + val up2dateProcessScanner = Scanner(up2dateProcess.getInputStream()!!) + val up2dateText = StringBuilder() + while (up2dateProcessScanner.hasNextLine()) { + up2dateText append up2dateProcessScanner.nextLine() + up2dateText append "\n" + } + up2dateProcessScanner.close() + + val up2dateResult = up2dateProcess.waitFor() + val up2dateBuildOutput = up2dateText.toString() + + println(up2dateBuildOutput) + + assertEquals(up2dateResult, 0) + assertTrue(up2dateBuildOutput.contains(":compileFlavor1DebugKotlin UP-TO-DATE"), "Should contain ':compileFlavor1DebugKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor2DebugKotlin UP-TO-DATE"), "Should contain ':compileFlavor2DebugKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor1JnidebugKotlin UP-TO-DATE"), "Should contain ':compileFlavor1JnidebugKotlin' UP-TO-DATE") + assertTrue(up2dateBuildOutput.contains(":compileFlavor1ReleaseKotlin UP-TO-DATE"), "Should contain ':compileFlavor1ReleaseKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor2JnidebugKotlin UP-TO-DATE"), "Should contain ':compileFlavor2JnidebugKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor2ReleaseKotlin UP-TO-DATE"), "Should contain ':compileFlavor2ReleaseKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor1Debug UP-TO-DATE"), "Should contain ':compileFlavor1Debug UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor2Debug UP-TO-DATE"), "Should contain ':compileFlavor2Debug UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor1Jnidebug UP-TO-DATE"), "Should contain ':compileFlavor1Jnidebug UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor2Jnidebug UP-TO-DATE"), "Should contain ':compileFlavor2Jnidebug UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor1Release UP-TO-DATE"), "Should contain ':compileFlavor1Release UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileFlavor2Release UP-TO-DATE"), "Should contain ':compileFlavor2Release UP-TO-DATE'") + } + + + fun copyRecursively(source: File, target: File) { + assertTrue(target.isDirectory()) + val targetFile = File(target, source.getName()) + if (source.isDirectory()) { + targetFile.mkdir() + val array = source.listFiles() + if (array != null) { + for (child in array) { + copyRecursively(child, targetFile) + } + } + } else { + Files.copy(source, targetFile) + } + } + + + fun deleteRecursively(f: File): Unit { + if (f.isDirectory()) { + val children = f.listFiles() + if (children != null) { + for (child in children) { + deleteRecursively(child) + } + } + val shouldBeEmpty = f.listFiles() + if (shouldBeEmpty != null) { + assertTrue(shouldBeEmpty.isEmpty()) + } else { + fail("Error listing directory content") + } + } + f.delete() + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt index 68f085a6eae..89fe98e61f3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -19,7 +19,6 @@ class BasicKotlinGradleIT { Before fun setUp() { workingDir = Files.createTempDir() workingDir.mkdirs() - copyRecursively(File("src/test/resources/testProject/alfa"), workingDir) } @@ -27,15 +26,16 @@ class BasicKotlinGradleIT { deleteRecursively(workingDir) } - Test fun testSimpleCompile() { + Test fun testCrossCompile() { + copyRecursively(File("src/test/resources/testProject/alfa"), workingDir) val projectDir = File(workingDir, "alfa") - val pathToKotlinPluginWrapper = "-PpathToKotlinPluginWrapper=" + File("local-repo").getAbsolutePath() - val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("../kotlin-gradle-plugin-core/local-repo").getAbsolutePath() + val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("local-repo").getAbsolutePath() + val cmd = if (SystemInfo.isWindows) - listOf("cmd", "/C", "gradlew.bat", "compileDeployKotlin", "build", pathToKotlinPluginWrapper, pathToKotlinPlugin, "--no-daemon", "--debug") + listOf("cmd", "/C", "gradlew.bat", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug") else - listOf("/bin/bash", "./gradlew", "compileDeployKotlin", "build", pathToKotlinPluginWrapper, pathToKotlinPlugin, "--no-daemon", "--debug") + listOf("/bin/bash", "./gradlew", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug") val builder = ProcessBuilder(cmd) builder.directory(projectDir) @@ -89,6 +89,64 @@ class BasicKotlinGradleIT { } + Test fun testKotlinOnlyCompile() { + copyRecursively(File("src/test/resources/testProject/beta"), workingDir) + val projectDir = File(workingDir, "beta") + + val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("local-repo").getAbsolutePath() + + val cmd = if (SystemInfo.isWindows) + listOf("cmd", "/C", "gradlew.bat", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + else + listOf("/bin/bash", "./gradlew", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + + val builder = ProcessBuilder(cmd) + builder.directory(projectDir) + builder.redirectErrorStream(true) + val process = builder.start() + + val s = Scanner(process.getInputStream()!!) + val text = StringBuilder() + while (s.hasNextLine()) { + text append s.nextLine() + text append "\n" + } + s.close() + + val result = process.waitFor() + val buildOutput = text.toString() + + println(buildOutput) + assertEquals(result, 0) + assertTrue(buildOutput.contains(":compileKotlin"), "Should contain ':compileKotlin'") + assertTrue(buildOutput.contains(":compileTestKotlin"), "Should contain ':compileTestKotlin'") + assertTrue(File(projectDir, "build/reports/tests/demo.TestSource.html").exists(), "Test report does not exist. Were tests executed?") + + // Run the build second time, assert everything is up-to-date + + val up2dateBuilder = ProcessBuilder(cmd) + up2dateBuilder.directory(projectDir) + up2dateBuilder.redirectErrorStream(true) + val up2dateProcess = up2dateBuilder.start() + + val up2dateProcessScanner = Scanner(up2dateProcess.getInputStream()!!) + val up2dateText = StringBuilder() + while (up2dateProcessScanner.hasNextLine()) { + up2dateText append up2dateProcessScanner.nextLine() + up2dateText append "\n" + } + up2dateProcessScanner.close() + + val up2dateResult = up2dateProcess.waitFor() + val up2dateBuildOutput = up2dateText.toString() + + println(up2dateBuildOutput) + + assertEquals(up2dateResult, 0) + assertTrue(up2dateBuildOutput.contains(":compileKotlin UP-TO-DATE"), "Should contain ':compileKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileTestKotlin UP-TO-DATE"), "Should contain ':compileTestKotlin UP-TO-DATE'") + } + fun copyRecursively(source: File, target: File) { assertTrue(target.isDirectory()) val targetFile = File(target, source.getName()) diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/build.gradle b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/build.gradle new file mode 100644 index 00000000000..ecaea3c8db6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/build.gradle @@ -0,0 +1,52 @@ +buildscript { + repositories { + mavenCentral() + maven { + url 'file://' + pathToKotlinPlugin + } + } + dependencies { + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT' + classpath 'com.android.tools.build:gradle:0.4' + } +} +apply plugin: 'android' +apply plugin: 'kotlin-android' + +dependencies { + compile files('libs/android-support-v4.jar') +} + +android { + compileSdkVersion 17 + buildToolsVersion "17.0.0" + + kotlinOptions { + annotations = "kotlinAnnotations" + } + + defaultConfig { + minSdkVersion 7 + targetSdkVersion 16 + } + + buildTypes { + jnidebug.initWith(buildTypes.debug) + jnidebug { + packageNameSuffix ".jnidebug" + jniDebugBuild true + } + } + + productFlavors { + flavor1 { + packageName "com.example.flavor1" + versionCode 20 + } + + flavor2 { + packageName "com.example.flavor2" + minSdkVersion 14 + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/libs/android-support-v4.jar b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/libs/android-support-v4.jar new file mode 100644 index 00000000000..428bdbc02a1 Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/libs/android-support-v4.jar differ diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/AndroidManifest.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..377e183029c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/java/org/jetbrains/kotlin/gradle/test/androidalfa/MainActivity.java b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/java/org/jetbrains/kotlin/gradle/test/androidalfa/MainActivity.java new file mode 100644 index 00000000000..c585d40700d --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/java/org/jetbrains/kotlin/gradle/test/androidalfa/MainActivity.java @@ -0,0 +1,36 @@ +package org.jetbrains.kotlin.gradle.test.androidalfa; + +import android.content.Intent; +import android.os.Bundle; +import android.app.Activity; +import android.view.Menu; +import android.view.View; +import android.widget.Button; + +import org.jetbrains.kotlin.gradle.test.androidalfa.R; + +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Button next = (Button) findViewById(R.id.Button01); + next.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + Intent myIntent = new Intent(view.getContext(), MainActivity2.class); + startActivityForResult(myIntent, 0); + } + }); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/kotlin/org/jetbrains/kotlin/gradle/test/androidalfa/MainActivity2.kt b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/kotlin/org/jetbrains/kotlin/gradle/test/androidalfa/MainActivity2.kt new file mode 100644 index 00000000000..06d9cb69f92 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/kotlin/org/jetbrains/kotlin/gradle/test/androidalfa/MainActivity2.kt @@ -0,0 +1,33 @@ +package org.jetbrains.kotlin.gradle.test.androidalfa + +import android.content.Intent +import android.os.Bundle +import android.app.Activity +import android.view.Menu +import android.view.View +import android.widget.Button +import org.jetbrains.kotlin.gradle.test.androidalfa.R + +open class MainActivity2: Activity() { + + protected override fun onCreate(savedInstanceState: Bundle?): Unit { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main2) + + var next: Button = findViewById(R.id.Button02) as Button + next.setOnClickListener(object: View.OnClickListener { + public override fun onClick(view: View?): Unit { + val intent: Intent = Intent() + setResult(Activity.RESULT_OK, intent) + finish() + } + }) + } + + public override fun onCreateOptionsMenu(menu: Menu?): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main_activity2, menu); + return true + } + +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-hdpi/ic_launcher.png b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 00000000000..96a442e5b8e Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-mdpi/ic_launcher.png b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 00000000000..359047dfa4e Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-xhdpi/ic_launcher.png b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 00000000000..71c6d760f05 Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/layout/activity_main.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000000..ede57c3902f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/layout/activity_main.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/layout/activity_main2.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/layout/activity_main2.xml new file mode 100644 index 00000000000..d707536a92f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/layout/activity_main2.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/menu/main.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/menu/main.xml new file mode 100644 index 00000000000..f3b10b6c021 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/menu/main.xml @@ -0,0 +1,6 @@ + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/menu/main_activity2.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/menu/main_activity2.xml new file mode 100644 index 00000000000..f3b10b6c021 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/menu/main_activity2.xml @@ -0,0 +1,6 @@ + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-sw600dp/dimens.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-sw600dp/dimens.xml new file mode 100644 index 00000000000..886b05fa964 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-sw600dp/dimens.xml @@ -0,0 +1,4 @@ + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-sw720dp-land/dimens.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-sw720dp-land/dimens.xml new file mode 100644 index 00000000000..00059fc5c3f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-sw720dp-land/dimens.xml @@ -0,0 +1,5 @@ + + + 128dp + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-v11/styles.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-v11/styles.xml new file mode 100644 index 00000000000..3c02242ad04 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-v11/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-v14/styles.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-v14/styles.xml new file mode 100644 index 00000000000..a91fd0372b2 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values-v14/styles.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/dimens.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/dimens.xml new file mode 100644 index 00000000000..47c82246738 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 16dp + 16dp + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/strings.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/strings.xml new file mode 100644 index 00000000000..afffaa8a836 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ + + + + AndroidAlfa + Settings + Hello world! + MainActivity1 + MainActivity2 + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/styles.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/styles.xml new file mode 100644 index 00000000000..6ce89c7ba43 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/AndroidAlfa/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/build.gradle b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/build.gradle new file mode 100644 index 00000000000..495c5038ea6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/build.gradle @@ -0,0 +1 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradle/wrapper/gradle-wrapper.jar b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..8c0fb64a869 Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradle/wrapper/gradle-wrapper.jar differ diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradle/wrapper/gradle-wrapper.properties b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..5c22dec0647 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 10 15:27:10 PDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.6-bin.zip diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradlew b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradlew new file mode 100644 index 00000000000..91a7e269e19 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradlew.bat b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradlew.bat new file mode 100644 index 00000000000..8a0b282aa68 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/kotlinAnnotations/android/app/annotations.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/kotlinAnnotations/android/app/annotations.xml new file mode 100644 index 00000000000..480db34155f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/kotlinAnnotations/android/app/annotations.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/local.properties b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/local.properties new file mode 100644 index 00000000000..c47520a1bed --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Studio. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. + +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=C:/Program Files (x86)/Android/android-studio/sdk \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/settings.gradle b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/settings.gradle new file mode 100644 index 00000000000..d2866b240ea --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/AndroidAlfaProject/settings.gradle @@ -0,0 +1 @@ +include ':AndroidAlfa' diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle index 451ac3de6c0..fa7750dd26d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle @@ -4,9 +4,6 @@ buildscript { maven { url 'file://' + pathToKotlinPlugin } - maven { - url 'file://' + pathToKotlinPluginWrapper - } } dependencies { classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT' @@ -14,6 +11,7 @@ buildscript { } apply plugin: "kotlin" +apply plugin: "java" sourceSets { deploy @@ -49,4 +47,4 @@ compileKotlin { task wrapper(type: Wrapper) { gradleVersion="1.4" -} \ No newline at end of file +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/build.gradle b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/build.gradle new file mode 100644 index 00000000000..ca020c5dfff --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/build.gradle @@ -0,0 +1,45 @@ +buildscript { + repositories { + mavenCentral() + maven { + url 'file://' + pathToKotlinPlugin + } + } + dependencies { + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT' + } +} + +apply plugin: "kotlin" + + +repositories { + maven { + url 'file://' + pathToKotlinPlugin + } + mavenCentral() +} + +dependencies { + compile 'com.google.guava:guava:12.0' + testCompile 'org.testng:testng:6.8' + testRuntime 'org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT' +} + +test { + useTestNG() +} + +task show << { + buildscript.configurations.classpath.each { println it } +} + + +compileKotlin { + kotlinOptions.annotations = "externalAnnotations" +} + + +task wrapper(type: Wrapper) { + gradleVersion="1.4" +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/externalAnnotations/com/google/common/base/annotations.xml b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/externalAnnotations/com/google/common/base/annotations.xml new file mode 100644 index 00000000000..be8ddab04a3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/externalAnnotations/com/google/common/base/annotations.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradle/wrapper/gradle-wrapper.jar b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..42d9b0e9c58 Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradle/wrapper/gradle-wrapper.jar differ diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradle/wrapper/gradle-wrapper.properties b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..90e63547fc6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Feb 28 14:00:49 MSK 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.4-bin.zip diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradlew b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradlew new file mode 100644 index 00000000000..91a7e269e19 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradlew.bat b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradlew.bat new file mode 100644 index 00000000000..8a0b282aa68 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/src/main/kotlin/helloWorld.kt b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/src/main/kotlin/helloWorld.kt new file mode 100644 index 00000000000..5db792c9294 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/src/main/kotlin/helloWorld.kt @@ -0,0 +1,22 @@ +package demo + +import com.google.common.primitives.Ints +import com.google.common.base.Joiner +import java.util.ArrayList + +class KotlinGreetingJoiner(val greeter : Greeter) { + + val names = ArrayList() + + fun addName(name : String?): Unit{ + names.add(name) + } + + fun getJoinedGreeting() : String? { + val joiner = Joiner.on(" and ").skipNulls(); + return "${greeter.greeting} ${joiner.join(names)}" + } +} + +public open class Greeter(val greeting : String) + diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/src/test/kotlin/tests.kt b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/src/test/kotlin/tests.kt new file mode 100644 index 00000000000..e631927f0ff --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/beta/src/test/kotlin/tests.kt @@ -0,0 +1,21 @@ +package demo + +import com.google.common.primitives.Ints +import com.google.common.base.Joiner +import org.testng.Assert.* +import org.testng.annotations.AfterMethod +import org.testng.annotations.BeforeMethod +import org.testng.annotations.Test as test + +class TestSource() { + test fun f() { + val example : KotlinGreetingJoiner = KotlinGreetingJoiner(Greeter("Hi")) + example.addName("Harry") + example.addName("Ron") + example.addName(null) + example.addName("Hermione") + + assertEquals(example.getJoinedGreeting(), "Hi Harry and Ron and Hermione") + } +} + diff --git a/libraries/tools/kotlin-js-tests-junit/pom.xml b/libraries/tools/kotlin-js-tests-junit/pom.xml index 0f560b76fdc..17fd627f8ea 100644 --- a/libraries/tools/kotlin-js-tests-junit/pom.xml +++ b/libraries/tools/kotlin-js-tests-junit/pom.xml @@ -60,6 +60,14 @@ + + + maven-deploy-plugin + + true + + + diff --git a/libraries/tools/kotlin-js-tests/pom.xml b/libraries/tools/kotlin-js-tests/pom.xml index 29169628c6c..466704bcf13 100644 --- a/libraries/tools/kotlin-js-tests/pom.xml +++ b/libraries/tools/kotlin-js-tests/pom.xml @@ -108,6 +108,14 @@ + + + maven-deploy-plugin + + true + + + diff --git a/libraries/tools/kotlin-stdlib-gen/pom.xml b/libraries/tools/kotlin-stdlib-gen/pom.xml index e9826587687..4184d4ff781 100644 --- a/libraries/tools/kotlin-stdlib-gen/pom.xml +++ b/libraries/tools/kotlin-stdlib-gen/pom.xml @@ -3,26 +3,37 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - 4.0.0 + 4.0.0 - - org.jetbrains.kotlin - kotlin-project + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + kotlin-stdlib-gen + kotlin-stdlib-gen 0.1-SNAPSHOT - ../../pom.xml - - - kotlin-stdlib-gen - kotlin-stdlib-gen - 0.1-SNAPSHOT - - - org.jetbrains.kotlin - kotlin-stdlib - ${project.version} - - + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + + + + + maven-deploy-plugin + + true + + + + \ No newline at end of file