From 3a8fb5feec92a95a9b46b4b0a214c76aba7bdd87 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 8 Nov 2016 10:59:22 +0100 Subject: [PATCH] move some useful read/write abstractions to DataInputOutputUtil --- .../dataFlow/MethodDataExternalizer.kt | 60 +++++++------------ .../intellij/util/io/DataInputOutputUtil.java | 50 ++++++++++++++++ 2 files changed, 73 insertions(+), 37 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodDataExternalizer.kt b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodDataExternalizer.kt index 621d0234c0c3..039bf87a9236 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodDataExternalizer.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodDataExternalizer.kt @@ -16,7 +16,7 @@ package com.intellij.codeInspection.dataFlow import com.intellij.util.io.DataExternalizer -import com.intellij.util.io.DataInputOutputUtil +import com.intellij.util.io.DataInputOutputUtil.* import java.io.DataInput import java.io.DataOutput @@ -26,24 +26,24 @@ import java.io.DataOutput internal object MethodDataExternalizer : DataExternalizer> { override fun save(out: DataOutput, value: Map?) { - writeList(out, value!!.toList()) { DataInputOutputUtil.writeINT(out, it.first); writeMethod(out, it.second) } + writeSeq(out, value!!.toList()) { writeINT(out, it.first); writeMethod(out, it.second) } } - override fun read(input: DataInput) = readList(input) { DataInputOutputUtil.readINT(input) to readMethod(input) }.toMap() + override fun read(input: DataInput) = readSeq(input) { readINT(input) to readMethod(input) }.toMap() private fun writeMethod(out: DataOutput, data: MethodData) { writeNullable(out, data.nullity) { writeNullity(out, it) } writeNullable(out, data.purity) { writePurity(out, it) } - writeList(out, data.contracts) { writeContract(out, it) } - DataInputOutputUtil.writeINT(out, data.bodyStart) - DataInputOutputUtil.writeINT(out, data.bodyEnd) + writeSeq(out, data.contracts) { writeContract(out, it) } + writeINT(out, data.bodyStart) + writeINT(out, data.bodyEnd) } private fun readMethod(input: DataInput): MethodData { val nullity = readNullable(input) { readNullity(input) } val purity = readNullable(input) { readPurity(input) } - val contracts = readList(input) { readContract(input) } - return MethodData(nullity, purity, contracts, DataInputOutputUtil.readINT(input), DataInputOutputUtil.readINT(input)) + val contracts = readSeq(input) { readContract(input) } + return MethodData(nullity, purity, contracts, readINT(input), readINT(input)) } private fun writeNullity(out: DataOutput, nullity: NullityInferenceResult) = when (nullity) { @@ -56,14 +56,14 @@ internal object MethodDataExternalizer : DataExternalizer> else -> NullityInferenceResult.FromDelegate(readRanges(input)) } - private fun writeRanges(out: DataOutput, ranges: List) = writeList(out, ranges) { writeRange(out, it) } - private fun readRanges(input: DataInput) = readList(input) { readRange(input) } + private fun writeRanges(out: DataOutput, ranges: List) = writeSeq(out, ranges) { writeRange(out, it) } + private fun readRanges(input: DataInput) = readSeq(input) { readRange(input) } private fun writeRange(out: DataOutput, range: ExpressionRange) { - DataInputOutputUtil.writeINT(out, range.startOffset) - DataInputOutputUtil.writeINT(out, range.endOffset) + writeINT(out, range.startOffset) + writeINT(out, range.endOffset) } - private fun readRange(input: DataInput) = ExpressionRange(DataInputOutputUtil.readINT(input), DataInputOutputUtil.readINT(input)) + private fun readRange(input: DataInput) = ExpressionRange(readINT(input), readINT(input)) private fun writePurity(out: DataOutput, purity: PurityInferenceResult) { writeRanges(out, purity.mutatedRefs) @@ -73,47 +73,33 @@ internal object MethodDataExternalizer : DataExternalizer> private fun writeContract(out: DataOutput, contract: PreContract): Unit = when (contract) { is DelegationContract -> { out.writeByte(0); writeRange(out, contract.expression); out.writeBoolean(contract.negated) } - is KnownContract -> { out.writeByte(1); + is KnownContract -> { out.writeByte(1) writeContractArguments(out, contract.contract.arguments.toList()) out.writeByte(contract.contract.returnValue.ordinal) } - is MethodCallContract -> { out.writeByte(2); - writeRange(out, contract.call); - writeList(out, contract.states) { writeContractArguments(out, it) } + is MethodCallContract -> { out.writeByte(2) + writeRange(out, contract.call) + writeSeq(out, contract.states) { writeContractArguments(out, it) } } is NegatingContract -> { out.writeByte(3); writeContract(out, contract.negated) } - is SideEffectFilter -> { out.writeByte(4); + is SideEffectFilter -> { out.writeByte(4) writeRanges(out, contract.expressionsToCheck) - writeList(out, contract.contracts) { writeContract(out, it) } + writeSeq(out, contract.contracts) { writeContract(out, it) } } else -> throw IllegalArgumentException(contract.toString()) } private fun readContract(input: DataInput): PreContract = when (input.readByte().toInt()) { 0 -> DelegationContract(readRange(input), input.readBoolean()) 1 -> KnownContract(MethodContract(readContractArguments(input).toTypedArray(), readValueConstraint(input))) - 2 -> MethodCallContract(readRange(input), readList(input) { readContractArguments(input) }) + 2 -> MethodCallContract(readRange(input), readSeq(input) { readContractArguments(input) }) 3 -> NegatingContract(readContract(input)) - else -> SideEffectFilter(readRanges(input), readList(input) { readContract(input) }) + else -> SideEffectFilter(readRanges(input), readSeq(input) { readContract(input) }) } private fun writeContractArguments(out: DataOutput, arguments: List) = - writeList(out, arguments) { out.writeByte(it.ordinal) } - private fun readContractArguments(input: DataInput) = readList(input, { readValueConstraint(input) }) + writeSeq(out, arguments) { out.writeByte(it.ordinal) } + private fun readContractArguments(input: DataInput) = readSeq(input, { readValueConstraint(input) }) private fun readValueConstraint(input: DataInput) = MethodContract.ValueConstraint.values()[input.readByte().toInt()] } - -// utils - -private fun writeNullable(out: DataOutput, value: T?, writeItem: (T) -> Unit) = when (value) { - null -> out.writeBoolean(false) - else -> { out.writeBoolean(true); writeItem(value) } -} -private fun readNullable(input: DataInput, readEach: () -> T): T? = if (input.readBoolean()) readEach() else null - -private fun writeList(out: DataOutput, list: List, writeEach: (T) -> Unit) { - DataInputOutputUtil.writeINT(out, list.size) - list.forEach(writeEach) -} -private fun readList(input: DataInput, readEach: () -> T) = (0 until DataInputOutputUtil.readINT(input)).map { readEach() } diff --git a/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java b/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java index 5311608a7dc9..b103889d8c63 100644 --- a/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java +++ b/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java @@ -15,12 +15,17 @@ */ package com.intellij.util.io; +import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.util.ThrowableConsumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * @author max @@ -139,4 +144,49 @@ public class DataInputOutputUtil { return ((((long)((first << 8) | second)) << 24) | (third | fourth | fifth)) + timeBase; } } + + /** + * Writes the given collection to the output using the given procedure to write each element. + * Should be coupled with {@link #readSeq} + */ + public static void writeSeq(@NotNull DataOutput out, @NotNull Collection collection, @NotNull ThrowableConsumer writeElement) throws IOException { + writeINT(out, collection.size()); + for (T t : collection) { + writeElement.consume(t); + } + } + + /** + * Reads a collection using the given function to read each element. + * Should be coupled with {@link #writeSeq} + */ + @NotNull + public static List readSeq(@NotNull DataInput in, @NotNull ThrowableComputable readElement) throws IOException { + int size = readINT(in); + List result = new ArrayList(size); + for (int i = 0; i < size; i++) { + result.add(readElement.compute()); + } + return result; + } + + /** + * Writes the given (possibly null) element to the output using the given procedure to write the element if it's not null. + * Should be coupled with {@link #readNullable} + */ + public static void writeNullable(@NotNull DataOutput out, @Nullable T value, @NotNull ThrowableConsumer writeValue) + throws IOException { + out.writeBoolean(value != null); + if (value != null) writeValue.consume(value); + } + + /** + * Reads an element from the stream, using the given function to read it when a not-null element is expected, or returns null otherwise. + * Should be coupled with {@link #writeNullable} + */ + @Nullable + public static T readNullable(@NotNull DataInput in, @NotNull ThrowableComputable readValue) throws IOException { + return in.readBoolean() ? readValue.compute() : null; + } + } \ No newline at end of file