?: supported
This commit is contained in:
@@ -17,6 +17,7 @@ public class JetTypeChecker {
|
|||||||
this.standardLibrary = standardLibrary;
|
this.standardLibrary = standardLibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private Map<TypeConstructor, Set<TypeConstructor>> getConversionMap() {
|
private Map<TypeConstructor, Set<TypeConstructor>> getConversionMap() {
|
||||||
// if (conversionMap.size() == 0) {
|
// if (conversionMap.size() == 0) {
|
||||||
// addConversion(standardLibrary.getByte(),
|
// addConversion(standardLibrary.getByte(),
|
||||||
@@ -62,7 +63,13 @@ public class JetTypeChecker {
|
|||||||
// conversionMap.put(actual.getTypeConstructor(), new HashSet<TypeConstructor>(Arrays.asList(constructors)));
|
// conversionMap.put(actual.getTypeConstructor(), new HashSet<TypeConstructor>(Arrays.asList(constructors)));
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
public JetType commonSupertype(Collection<JetType> types) {
|
@NotNull
|
||||||
|
public JetType commonSupertype(@NotNull JetType... types) {
|
||||||
|
return commonSupertype(Arrays.asList(types));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType commonSupertype(@NotNull Collection<JetType> types) {
|
||||||
Collection<JetType> typeSet = new HashSet<JetType>(types);
|
Collection<JetType> typeSet = new HashSet<JetType>(types);
|
||||||
assert !typeSet.isEmpty();
|
assert !typeSet.isEmpty();
|
||||||
boolean nullable = false;
|
boolean nullable = false;
|
||||||
@@ -98,7 +105,8 @@ public class JetTypeChecker {
|
|||||||
return TypeUtils.makeNullableIfNeeded(result, nullable);
|
return TypeUtils.makeNullableIfNeeded(result, nullable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetType computeSupertypeProjections(TypeConstructor constructor, Set<JetType> types) {
|
@NotNull
|
||||||
|
private JetType computeSupertypeProjections(@NotNull TypeConstructor constructor, @NotNull Set<JetType> types) {
|
||||||
// we assume that all the given types are applications of the same type constructor
|
// we assume that all the given types are applications of the same type constructor
|
||||||
|
|
||||||
assert !types.isEmpty();
|
assert !types.isEmpty();
|
||||||
@@ -127,7 +135,8 @@ public class JetTypeChecker {
|
|||||||
return new JetTypeImpl(Collections.<Attribute>emptyList(), constructor, nullable, newProjections, JetStandardClasses.STUB);
|
return new JetTypeImpl(Collections.<Attribute>emptyList(), constructor, nullable, newProjections, JetStandardClasses.STUB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeProjection computeSupertypeProjection(TypeParameterDescriptor parameterDescriptor, Set<TypeProjection> typeProjections) {
|
@NotNull
|
||||||
|
private TypeProjection computeSupertypeProjection(@NotNull TypeParameterDescriptor parameterDescriptor, @NotNull Set<TypeProjection> typeProjections) {
|
||||||
if (typeProjections.size() == 1) {
|
if (typeProjections.size() == 1) {
|
||||||
return typeProjections.iterator().next();
|
return typeProjections.iterator().next();
|
||||||
}
|
}
|
||||||
@@ -183,7 +192,8 @@ public class JetTypeChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<TypeConstructor, Set<JetType>> computeCommonRawSupertypes(Collection<JetType> types) {
|
@NotNull
|
||||||
|
private Map<TypeConstructor, Set<JetType>> computeCommonRawSupertypes(@NotNull Collection<JetType> types) {
|
||||||
assert !types.isEmpty();
|
assert !types.isEmpty();
|
||||||
|
|
||||||
final Map<TypeConstructor, Set<JetType>> constructorToAllInstances = new HashMap<TypeConstructor, Set<JetType>>();
|
final Map<TypeConstructor, Set<JetType>> constructorToAllInstances = new HashMap<TypeConstructor, Set<JetType>>();
|
||||||
@@ -244,19 +254,19 @@ public class JetTypeChecker {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markAll(TypeConstructor typeConstructor, Set<TypeConstructor> markerSet) {
|
private void markAll(@NotNull TypeConstructor typeConstructor, @NotNull Set<TypeConstructor> markerSet) {
|
||||||
markerSet.add(typeConstructor);
|
markerSet.add(typeConstructor);
|
||||||
for (JetType type : typeConstructor.getSupertypes()) {
|
for (JetType type : typeConstructor.getSupertypes()) {
|
||||||
markAll(type.getConstructor(), markerSet);
|
markAll(type.getConstructor(), markerSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <R> R dfs(JetType current, Set<TypeConstructor> visited, DfsNodeHandler<R> handler) {
|
private <R> R dfs(@NotNull JetType current, @NotNull Set<TypeConstructor> visited, @NotNull DfsNodeHandler<R> handler) {
|
||||||
doDfs(current, visited, handler);
|
doDfs(current, visited, handler);
|
||||||
return handler.result();
|
return handler.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doDfs(JetType current, Set<TypeConstructor> visited, DfsNodeHandler<?> handler) {
|
private void doDfs(@NotNull JetType current, @NotNull Set<TypeConstructor> visited, @NotNull DfsNodeHandler<?> handler) {
|
||||||
if (!visited.add(current.getConstructor())) {
|
if (!visited.add(current.getConstructor())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -307,7 +317,7 @@ public class JetTypeChecker {
|
|||||||
// This method returns the supertype of the first parameter that has the same constructor
|
// This method returns the supertype of the first parameter that has the same constructor
|
||||||
// as the second parameter, applying the substitution of type arguments to it
|
// as the second parameter, applying the substitution of type arguments to it
|
||||||
@Nullable
|
@Nullable
|
||||||
private JetType findCorrespondingSupertype(JetType subtype, JetType supertype) {
|
private JetType findCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
TypeConstructor constructor = subtype.getConstructor();
|
TypeConstructor constructor = subtype.getConstructor();
|
||||||
if (constructor.equals(supertype.getConstructor())) {
|
if (constructor.equals(supertype.getConstructor())) {
|
||||||
return subtype;
|
return subtype;
|
||||||
@@ -321,7 +331,7 @@ public class JetTypeChecker {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkSubtypeForTheSameConstructor(JetType subtype, JetType supertype) {
|
private boolean checkSubtypeForTheSameConstructor(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
TypeConstructor constructor = subtype.getConstructor();
|
TypeConstructor constructor = subtype.getConstructor();
|
||||||
assert constructor.equals(supertype.getConstructor());
|
assert constructor.equals(supertype.getConstructor());
|
||||||
|
|
||||||
|
|||||||
@@ -728,6 +728,18 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
result = semanticServices.getStandardLibrary().getBooleanType();
|
result = semanticServices.getStandardLibrary().getBooleanType();
|
||||||
}
|
}
|
||||||
|
else if (operationType == JetTokens.ELVIS) {
|
||||||
|
JetType leftType = getType(scope, left, false);
|
||||||
|
JetType rightType = right == null ? null : getType(scope, right, false);
|
||||||
|
if (leftType != null) {
|
||||||
|
if (!leftType.isNullable()) {
|
||||||
|
semanticServices.getErrorHandler().genericWarning(left.getNode(), "Elvis operator (?:) is always returns the left operand of non-nullable type " + leftType);
|
||||||
|
}
|
||||||
|
if (rightType != null) {
|
||||||
|
result = TypeUtils.makeNullableAsSpecified(semanticServices.getTypeChecker().commonSupertype(leftType, rightType), rightType.isNullable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
semanticServices.getErrorHandler().genericError(operationSign.getNode(), "Unknown operation");
|
semanticServices.getErrorHandler().genericError(operationSign.getNode(), "Unknown operation");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,18 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class TypeUtils {
|
public class TypeUtils {
|
||||||
public static JetType makeNullable(JetType type) {
|
public static JetType makeNullable(JetType type) {
|
||||||
if (type.isNullable()) {
|
return makeNullableAsSpecified(type, true);
|
||||||
return type;
|
|
||||||
}
|
|
||||||
return new JetTypeImpl(type.getAttributes(), type.getConstructor(), true, type.getArguments(), type.getMemberScope());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JetType makeNotNullable(JetType type) {
|
public static JetType makeNotNullable(JetType type) {
|
||||||
if (!type.isNullable()) {
|
return makeNullableAsSpecified(type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JetType makeNullableAsSpecified(JetType type, boolean nullable) {
|
||||||
|
if (type.isNullable() == nullable) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
return new JetTypeImpl(type.getAttributes(), type.getConstructor(), false, type.getArguments(), type.getMemberScope());
|
return new JetTypeImpl(type.getAttributes(), type.getConstructor(), nullable, type.getArguments(), type.getMemberScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -405,6 +405,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
|||||||
assertType("1 !== null", "Boolean");
|
assertType("1 !== null", "Boolean");
|
||||||
assertType("true && false", "Boolean");
|
assertType("true && false", "Boolean");
|
||||||
assertType("true || false", "Boolean");
|
assertType("true || false", "Boolean");
|
||||||
|
assertType("null ?: false", "Boolean");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertSubtype(String type1, String type2) {
|
private void assertSubtype(String type1, String type2) {
|
||||||
|
|||||||
Reference in New Issue
Block a user