Data flow value converted to Kotlin
This commit is contained in:
+1
-1
@@ -418,7 +418,7 @@ public class JavaNullabilityWarningsChecker : AdditionalTypeChecker {
|
|||||||
|
|
||||||
private fun <T: Any> doIfNotNull(dataFlowValue: DataFlowValue, c: ResolutionContext<*>, body: () -> T): T? {
|
private fun <T: Any> doIfNotNull(dataFlowValue: DataFlowValue, c: ResolutionContext<*>, body: () -> T): T? {
|
||||||
if (c.dataFlowInfo.getNullability(dataFlowValue).canBeNull()
|
if (c.dataFlowInfo.getNullability(dataFlowValue).canBeNull()
|
||||||
&& dataFlowValue.getType().mustNotBeNull() == NullabilityInformationSource.JAVA) {
|
&& dataFlowValue.type.mustNotBeNull() == NullabilityInformationSource.JAVA) {
|
||||||
return body()
|
return body()
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
|||||||
+1
-1
@@ -184,7 +184,7 @@ class GenericCandidateResolver(
|
|||||||
if (deparenthesizedArgument == null || type == null) return type
|
if (deparenthesizedArgument == null || type == null) return type
|
||||||
|
|
||||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
|
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
|
||||||
if (!dataFlowValue.isPredictable()) return type
|
if (!dataFlowValue.isPredictable) return type
|
||||||
|
|
||||||
val possibleTypes = context.dataFlowInfo.getPossibleTypes(dataFlowValue)
|
val possibleTypes = context.dataFlowInfo.getPossibleTypes(dataFlowValue)
|
||||||
if (possibleTypes.isEmpty()) return type
|
if (possibleTypes.isEmpty()) return type
|
||||||
|
|||||||
-123
@@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 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.kotlin.resolve.calls.smartcasts;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils;
|
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class describes an arbitrary object which has some value in data flow analysis.
|
|
||||||
* In general case it's some r-value.
|
|
||||||
*/
|
|
||||||
public class DataFlowValue {
|
|
||||||
|
|
||||||
public enum Kind {
|
|
||||||
STABLE_VALUE("stable"),
|
|
||||||
PREDICTABLE_VARIABLE("predictable"),
|
|
||||||
UNPREDICTABLE_VARIABLE("unpredictable"),
|
|
||||||
OTHER("other");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
Kind(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public boolean isStable() {
|
|
||||||
return this == STABLE_VALUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final DataFlowValue NULL = new DataFlowValue(new Object(), KotlinBuiltIns.getInstance().getNullableNothingType(), Kind.OTHER, Nullability.NULL);
|
|
||||||
public static final DataFlowValue ERROR = new DataFlowValue(new Object(), ErrorUtils.createErrorType("Error type for data flow"), Kind.OTHER, Nullability.IMPOSSIBLE);
|
|
||||||
|
|
||||||
private final Kind kind;
|
|
||||||
private final JetType type;
|
|
||||||
private final Object id;
|
|
||||||
private final Nullability immanentNullability;
|
|
||||||
|
|
||||||
// Use DataFlowValueFactory
|
|
||||||
/*package*/ DataFlowValue(Object id, JetType type, Kind kind, Nullability immanentNullability) {
|
|
||||||
this.kind = kind;
|
|
||||||
this.type = type;
|
|
||||||
this.id = id;
|
|
||||||
this.immanentNullability = immanentNullability;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Object getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Nullability getImmanentNullability() {
|
|
||||||
return immanentNullability;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Kind getKind() {
|
|
||||||
return kind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Both stable values and local variables (regardless captured or not) are considered "predictable".
|
|
||||||
* Predictable means here we do not expect some sudden change of their values,
|
|
||||||
* like accessing mutable properties in another thread.
|
|
||||||
*/
|
|
||||||
public boolean isPredictable() {
|
|
||||||
return kind == Kind.STABLE_VALUE || kind == Kind.PREDICTABLE_VARIABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public JetType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
DataFlowValue that = (DataFlowValue) o;
|
|
||||||
|
|
||||||
if (kind.isStable() != that.kind.isStable()) return false;
|
|
||||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
|
||||||
if (type != null ? !type.equals(that.type) : that.type != null) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return kind.toString() + (id == null ? null : id.toString()) + " " + immanentNullability;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = kind.isStable() ? 1 : 0;
|
|
||||||
result = 31 * result + (type != null ? type.hashCode() : 0);
|
|
||||||
result = 31 * result + (id != null ? id.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.kotlin.resolve.calls.smartcasts
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class describes an arbitrary object which has some value in data flow analysis.
|
||||||
|
* In general case it's some r-value.
|
||||||
|
*/
|
||||||
|
class DataFlowValue(val id: Any?, val type: JetType, val kind: DataFlowValue.Kind, val immanentNullability: Nullability) {
|
||||||
|
|
||||||
|
enum class Kind(private val name: String) {
|
||||||
|
// Smart casts are completely safe
|
||||||
|
STABLE_VALUE("stable"),
|
||||||
|
// Smart casts are safe but possible changes in loops / closures ahead must be taken into account
|
||||||
|
PREDICTABLE_VARIABLE("predictable"),
|
||||||
|
// Smart casts are not safe
|
||||||
|
UNPREDICTABLE_VARIABLE("unpredictable"),
|
||||||
|
OTHER("other");
|
||||||
|
|
||||||
|
override fun toString() = name
|
||||||
|
|
||||||
|
fun isStable() = this == STABLE_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Both stable values and predictable local variables are considered "predictable".
|
||||||
|
* Predictable means here we do not expect some sudden change of their values,
|
||||||
|
* like accessing mutable properties in another thread, so smart casts can be used safely.
|
||||||
|
*/
|
||||||
|
val isPredictable = (kind == Kind.STABLE_VALUE || kind == Kind.PREDICTABLE_VARIABLE)
|
||||||
|
@JvmName("isPredictable") get
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other !is DataFlowValue) return false
|
||||||
|
|
||||||
|
if (kind.isStable() != other.kind.isStable()) return false
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (type != other.type) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return kind.toString() + (id?.toString()) + " " + immanentNullability
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = if (kind.isStable()) 1 else 0
|
||||||
|
result = 31 * result + (type?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (id?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val NULL = DataFlowValue(Object(), KotlinBuiltIns.getInstance().nullableNothingType, Kind.OTHER, Nullability.NULL)
|
||||||
|
val ERROR = DataFlowValue(Object(), ErrorUtils.createErrorType("Error type for data flow"), Kind.OTHER, Nullability.IMPOSSIBLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
|||||||
|
|
||||||
fun renderDataFlowValue(value: DataFlowValue): String? {
|
fun renderDataFlowValue(value: DataFlowValue): String? {
|
||||||
// If it is not a stable identifier, there's no point in rendering it
|
// If it is not a stable identifier, there's no point in rendering it
|
||||||
if (!value.isPredictable()) return null
|
if (!value.isPredictable) return null
|
||||||
|
|
||||||
fun renderId(id: Any?): String? {
|
fun renderId(id: Any?): String? {
|
||||||
return when (id) {
|
return when (id) {
|
||||||
@@ -36,5 +36,5 @@ fun renderDataFlowValue(value: DataFlowValue): String? {
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return renderId(value.getId())
|
return renderId(value.id)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user