KT-2583 Support *Range.EMPTY
#KT-2583 fixed
This commit is contained in:
@@ -30,6 +30,8 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.*;
|
||||
@@ -65,6 +67,20 @@ public class ClosureAnnotator {
|
||||
public void init() {
|
||||
mapFilesToNamespaces(files);
|
||||
prepareAnonymousClasses();
|
||||
prepareClassObjectsForBuiltinRanges();
|
||||
}
|
||||
|
||||
private void prepareClassObjectsForBuiltinRanges() {
|
||||
// this is needed for range classes because they have class objects with
|
||||
// intrinsic members
|
||||
JetScope stdLibraryScope = JetStandardLibrary.getInstance().getLibraryScope();
|
||||
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
|
||||
ClassDescriptor klass = (ClassDescriptor) stdLibraryScope.getClassifier(type.getRangeTypeName());
|
||||
String rangeInternalName = JvmClassName.byFqNameWithoutInnerClasses(
|
||||
JetStandardClasses.STANDARD_CLASSES_FQNAME.child(type.getRangeTypeName())).getInternalName();
|
||||
JvmClassName classObjectInternalName = JvmClassName.byInternalName(rangeInternalName + JvmAbi.CLASS_OBJECT_SUFFIX);
|
||||
classNamesForClassDescriptor.put(klass.getClassObjectDescriptor(), classObjectInternalName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2012 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.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Evgeny Gerashchenko
|
||||
* @since 08.08.12
|
||||
*/
|
||||
public class EmptyRange implements IntrinsicMethod {
|
||||
private final PrimitiveType elementType;
|
||||
|
||||
public EmptyRange(PrimitiveType elementType) {
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen,
|
||||
InstructionAdapter v,
|
||||
@NotNull Type expectedType,
|
||||
@Nullable PsiElement element,
|
||||
@Nullable List<JetExpression> arguments,
|
||||
StackValue receiver,
|
||||
@NotNull GenerationState state) {
|
||||
JvmClassName name = JvmClassName.byFqNameWithoutInnerClasses(elementType.getRangeClassName().getFqName());
|
||||
v.getstatic(name.toString(), "empty", "L" + name + ";");
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
@@ -25,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -141,6 +140,12 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicProperty(Name.identifier("CharSequence"), Name.identifier("length"), new StringLength());
|
||||
declareIntrinsicProperty(Name.identifier("String"), Name.identifier("length"), new StringLength());
|
||||
|
||||
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
|
||||
intrinsicsMap.registerIntrinsic(
|
||||
JetStandardClasses.STANDARD_CLASSES_FQNAME.child(type.getRangeTypeName()).toUnsafe().child(JetPsiUtil.NO_NAME_PROVIDED),
|
||||
Name.identifier("EMPTY"), -1, new EmptyRange(type));
|
||||
}
|
||||
|
||||
declareArrayMethods();
|
||||
}
|
||||
|
||||
@@ -228,5 +233,4 @@ public class IntrinsicMethods {
|
||||
}
|
||||
return intrinsicMethod;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,11 +82,18 @@ class IntrinsicsMap {
|
||||
private Map<Key, IntrinsicMethod> intrinsicsMap = Maps.newHashMap();
|
||||
|
||||
|
||||
/**
|
||||
* @param valueParameterCount -1 for property
|
||||
*/
|
||||
public void registerIntrinsic(@NotNull FqNameUnsafe owner, @NotNull Name name, int valueParameterCount, @NotNull IntrinsicMethod impl) {
|
||||
intrinsicsMap.put(new Key(owner, name, valueParameterCount), impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param valueParameterCount -1 for property
|
||||
*/
|
||||
public void registerIntrinsic(@NotNull FqName owner, @NotNull Name name, int valueParameterCount, @NotNull IntrinsicMethod impl) {
|
||||
intrinsicsMap.put(new Key(owner.toUnsafe(), name, valueParameterCount), impl);
|
||||
registerIntrinsic(owner.toUnsafe(), name, valueParameterCount, impl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ public class IntRange(public val start : Int, public val size : Int) : Range<Int
|
||||
public fun step(step: Int) : IntIterator
|
||||
|
||||
public val isReversed : Boolean
|
||||
|
||||
public class object {
|
||||
public val EMPTY: IntRange
|
||||
}
|
||||
}
|
||||
|
||||
public class LongRange(public val start : Long, public val size : Long) : Range<Long>, LongIterable {
|
||||
@@ -34,6 +38,10 @@ public class LongRange(public val start : Long, public val size : Long) : Range<
|
||||
public fun step(step: Long) : LongIterator
|
||||
|
||||
public val isReversed : Boolean
|
||||
|
||||
public class object {
|
||||
public val EMPTY: LongRange
|
||||
}
|
||||
}
|
||||
|
||||
public class ByteRange(public val start : Byte, public val size : Int) : Range<Byte>, ByteIterable {
|
||||
@@ -50,6 +58,10 @@ public class ByteRange(public val start : Byte, public val size : Int) : Range<B
|
||||
public fun step(step: Int) : ByteIterator
|
||||
|
||||
public val isReversed : Boolean
|
||||
|
||||
public class object {
|
||||
public val EMPTY: ByteRange
|
||||
}
|
||||
}
|
||||
|
||||
public class ShortRange(public val start : Short, public val size : Int) : Range<Short>, ShortIterable {
|
||||
@@ -66,6 +78,10 @@ public class ShortRange(public val start : Short, public val size : Int) : Range
|
||||
public fun step(step: Int) : ShortIterator
|
||||
|
||||
public val isReversed : Boolean
|
||||
|
||||
public class object {
|
||||
public val EMPTY: ShortRange
|
||||
}
|
||||
}
|
||||
|
||||
public class CharRange(public val start : Char, public val size : Int) : Range<Char>, CharIterable {
|
||||
@@ -82,6 +98,10 @@ public class CharRange(public val start : Char, public val size : Int) : Range<C
|
||||
public fun step(step: Int) : CharIterator
|
||||
|
||||
public val isReversed : Boolean
|
||||
|
||||
public class object {
|
||||
public val EMPTY: CharRange
|
||||
}
|
||||
}
|
||||
|
||||
public class FloatRange(public val start : Float, public val size : Float) : Range<Float> {
|
||||
@@ -94,6 +114,10 @@ public class FloatRange(public val start : Float, public val size : Float) : Ran
|
||||
public fun step(step: Float) : FloatIterator
|
||||
|
||||
public val isReversed : Boolean
|
||||
|
||||
public class object {
|
||||
public val EMPTY: FloatRange
|
||||
}
|
||||
}
|
||||
|
||||
public class DoubleRange(public val start : Double, public val size : Double) : Range<Double> {
|
||||
@@ -106,4 +130,8 @@ public class DoubleRange(public val start : Double, public val size : Double) :
|
||||
public fun step(step: Double) : DoubleIterator
|
||||
|
||||
public val isReversed : Boolean
|
||||
|
||||
public class object {
|
||||
public val EMPTY: DoubleRange
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,10 @@ public final class jet.ByteRange : jet.Range<jet.Byte>, jet.ByteIterable {
|
||||
public final val size: jet.Int
|
||||
public final val start: jet.Byte
|
||||
public final fun step(/*0*/ step: jet.Int): jet.ByteIterator
|
||||
public final class object jet.ByteRange.<no name provided> : jet.Any {
|
||||
internal final /*constructor*/ fun <init>(): jet.ByteRange.<no name provided>
|
||||
public final val EMPTY: jet.ByteRange
|
||||
}
|
||||
}
|
||||
public final class jet.Char : jet.Number, jet.Comparable<jet.Char> {
|
||||
public final /*constructor*/ fun <init>(): jet.Char
|
||||
@@ -220,6 +224,10 @@ public final class jet.CharRange : jet.Range<jet.Char>, jet.CharIterable {
|
||||
public final val size: jet.Int
|
||||
public final val start: jet.Char
|
||||
public final fun step(/*0*/ step: jet.Int): jet.CharIterator
|
||||
public final class object jet.CharRange.<no name provided> : jet.Any {
|
||||
internal final /*constructor*/ fun <init>(): jet.CharRange.<no name provided>
|
||||
public final val EMPTY: jet.CharRange
|
||||
}
|
||||
}
|
||||
public abstract trait jet.CharSequence : jet.Any {
|
||||
public abstract fun get(/*0*/ index: jet.Int): jet.Char
|
||||
@@ -319,6 +327,10 @@ public final class jet.DoubleRange : jet.Range<jet.Double> {
|
||||
public final val size: jet.Double
|
||||
public final val start: jet.Double
|
||||
public final fun step(/*0*/ step: jet.Double): jet.DoubleIterator
|
||||
public final class object jet.DoubleRange.<no name provided> : jet.Any {
|
||||
internal final /*constructor*/ fun <init>(): jet.DoubleRange.<no name provided>
|
||||
public final val EMPTY: jet.DoubleRange
|
||||
}
|
||||
}
|
||||
public abstract class jet.ExtensionFunction0</*0*/ in T : jet.Any?, /*1*/ out R : jet.Any?> : jet.Any {
|
||||
public final /*constructor*/ fun </*0*/ in T : jet.Any?, /*1*/ out R : jet.Any?><init>(): jet.ExtensionFunction0<T, R>
|
||||
@@ -503,6 +515,10 @@ public final class jet.FloatRange : jet.Range<jet.Float> {
|
||||
public final val size: jet.Float
|
||||
public final val start: jet.Float
|
||||
public final fun step(/*0*/ step: jet.Float): jet.FloatIterator
|
||||
public final class object jet.FloatRange.<no name provided> : jet.Any {
|
||||
internal final /*constructor*/ fun <init>(): jet.FloatRange.<no name provided>
|
||||
public final val EMPTY: jet.FloatRange
|
||||
}
|
||||
}
|
||||
public abstract class jet.Function0</*0*/ out R : jet.Any?> : jet.Any {
|
||||
public final /*constructor*/ fun </*0*/ out R : jet.Any?><init>(): jet.Function0<R>
|
||||
@@ -700,6 +716,10 @@ public final class jet.IntRange : jet.Range<jet.Int>, jet.IntIterable {
|
||||
public final val size: jet.Int
|
||||
public final val start: jet.Int
|
||||
public final fun step(/*0*/ step: jet.Int): jet.IntIterator
|
||||
public final class object jet.IntRange.<no name provided> : jet.Any {
|
||||
internal final /*constructor*/ fun <init>(): jet.IntRange.<no name provided>
|
||||
public final val EMPTY: jet.IntRange
|
||||
}
|
||||
}
|
||||
public abstract trait jet.Iterable</*0*/ out T : jet.Any?> : jet.Any {
|
||||
public abstract fun iterator(): jet.Iterator<T>
|
||||
@@ -808,6 +828,10 @@ public final class jet.LongRange : jet.Range<jet.Long>, jet.LongIterable {
|
||||
public final val size: jet.Long
|
||||
public final val start: jet.Long
|
||||
public final fun step(/*0*/ step: jet.Long): jet.LongIterator
|
||||
public final class object jet.LongRange.<no name provided> : jet.Any {
|
||||
internal final /*constructor*/ fun <init>(): jet.LongRange.<no name provided>
|
||||
public final val EMPTY: jet.LongRange
|
||||
}
|
||||
}
|
||||
public final class jet.Nothing {
|
||||
private final /*constructor*/ fun <init>(): jet.Nothing
|
||||
@@ -920,6 +944,10 @@ public final class jet.ShortRange : jet.Range<jet.Short>, jet.ShortIterable {
|
||||
public final val size: jet.Int
|
||||
public final val start: jet.Short
|
||||
public final fun step(/*0*/ step: jet.Int): jet.ShortIterator
|
||||
public final class object jet.ShortRange.<no name provided> : jet.Any {
|
||||
internal final /*constructor*/ fun <init>(): jet.ShortRange.<no name provided>
|
||||
public final val EMPTY: jet.ShortRange
|
||||
}
|
||||
}
|
||||
public final class jet.String : jet.Comparable<jet.String>, jet.CharSequence {
|
||||
public final /*constructor*/ fun <init>(): jet.String
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
fun box(): String {
|
||||
if (IntRange(0, 0) != IntRange.EMPTY) {
|
||||
return IntRange.EMPTY.toString()
|
||||
}
|
||||
if (CharRange(0.toChar(), 0) != CharRange.EMPTY) {
|
||||
return CharRange.EMPTY.toString()
|
||||
}
|
||||
if (ByteRange(0, 0) != ByteRange.EMPTY) {
|
||||
return ByteRange.EMPTY.toString()
|
||||
}
|
||||
if (ShortRange(0, 0) != ShortRange.EMPTY) {
|
||||
return ShortRange.EMPTY.toString()
|
||||
}
|
||||
if (FloatRange(0.toFloat(), 0.toFloat()) != FloatRange.EMPTY) {
|
||||
return FloatRange.EMPTY.toString()
|
||||
}
|
||||
if (LongRange(0, 0) != LongRange.EMPTY) {
|
||||
return LongRange.EMPTY.toString()
|
||||
}
|
||||
if (DoubleRange(0.0, 0.0) != DoubleRange.EMPTY) {
|
||||
return DoubleRange.EMPTY.toString()
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -444,4 +444,8 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
||||
public void testKt2275() {
|
||||
blackBoxFile("regressions/kt2275.kt");
|
||||
}
|
||||
|
||||
public void testEmptyRanges() throws Exception {
|
||||
blackBoxFile("emptyRanges.kt");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user