Skip to content

Commit

Permalink
monospace length
Browse files Browse the repository at this point in the history
  • Loading branch information
robstoll committed Dec 16, 2024
1 parent bf546a5 commit 63b14f8
Show file tree
Hide file tree
Showing 30 changed files with 1,038 additions and 663 deletions.
596 changes: 298 additions & 298 deletions README.md

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion atrium-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ kotlin {
implementation(prefixedProject("specs"))
}
}
jvmMain {
dependencies {
implementation("org.opentest4j:opentest4j:1.3.0")
}
}
}
}

Expand All @@ -43,7 +48,8 @@ ifIsPublishing {

createGenerateCoreTask(
includingTarget("jvm"),
includingTarget("common",
includingTarget(
"common",
//TODO 1.3.0 enable once transitioned to proofs
// "/creating/charsequence/contains/creators" to { _ ->
// "<T : CharSequence, S : CharSequenceContains.SearchBehaviour> CharSequenceContains.CheckerStepLogic<T, S>" to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ import ch.tutteli.atrium.reporting.prerendering.text.impl.*
import ch.tutteli.atrium.reporting.prerendering.text.impl.assertion.*
import ch.tutteli.atrium.reporting.text.*
import ch.tutteli.atrium.reporting.text.impl.*
import ch.tutteli.atrium.reporting.theming.text.TextIconStyler
import ch.tutteli.atrium.reporting.theming.text.TextStyler
import ch.tutteli.atrium.reporting.theming.text.TextThemeProvider
import ch.tutteli.atrium.reporting.theming.text.Utf8SupportDeterminer
import ch.tutteli.atrium.reporting.theming.text.*
import ch.tutteli.atrium.reporting.theming.text.impl.*
import ch.tutteli.atrium.reporting.theming.text.impl.DefaultTextIconStyler
import ch.tutteli.atrium.reporting.theming.text.impl.DefaultTextStyler
import ch.tutteli.atrium.reporting.theming.text.impl.DefaultThemeProvider
Expand Down Expand Up @@ -142,7 +140,7 @@ internal object DefaultComponentFactoryContainer : ComponentFactoryContainer by
ReportableFilter.failingProofsAndNonProof()
},
TextIconStyler::class createSingletonVia { c ->
DefaultTextIconStyler(c.build(), c.build())
DefaultTextIconStyler(c.build(),c.build(), c.build())
},
TextStyler::class createSingletonVia { c ->
DefaultTextStyler(c.build())
Expand All @@ -152,14 +150,17 @@ internal object DefaultComponentFactoryContainer : ComponentFactoryContainer by
DefaultThemeProvider(c.build())
},
TextObjFormatter::class createVia { c ->
DefaultTextObjFormatter(c.build())
DefaultTextObjFormatter(c.build(), c.build())
},
Utf8SupportDeterminer::class createVia { c ->
MordantBasedUtf8SupportDeterminer(c.build())
},
Terminal::class createVia { _ ->
Terminal(ansiLevel = AnsiLevel.TRUECOLOR)
},
MonospaceLengthCalculator::class createVia { _ ->
StringLengthMonospaceLengthCalculator
},

//TODO 2.0.0 remove
@Suppress("DEPRECATION")
Expand Down Expand Up @@ -270,7 +271,7 @@ internal object DefaultComponentFactoryContainer : ComponentFactoryContainer by
{ c -> DefaultRowTextPreRenderer(c.build()) },
{ _ -> DefaultColumnTextPreRenderer() },
{ c -> DefaultRepresentationTextPreRenderer(c.build()) },
{ _ -> DefaultTextElementTextPreRenderer() },
{ c -> DefaultTextElementTextPreRenderer(c.build()) },
),
TextDesignationPreRenderer::class createChainVia sequenceOf(
{ c -> DefaultInlineDesignatorPreRenderer(c.build()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package ch.tutteli.atrium.reporting
import ch.tutteli.atrium.creating.proofs.Proof
import ch.tutteli.atrium.reporting.AtriumError.Companion


expect open class AssertionErrorLikeIntermediate : Error
expect open class AssertionErrorLike : AssertionErrorLikeIntermediate


/**
* Indicates that an expectation stated via Atrium was not.
*
Expand All @@ -12,7 +17,7 @@ import ch.tutteli.atrium.reporting.AtriumError.Companion
*
* To create such an error you need to use the [Companion.create] function.
*/
expect class AtriumError internal constructor(message: String, causingProof: Proof) : AssertionError {
expect class AtriumError internal constructor(message: String, causingProof: Proof) : AssertionErrorLike {

/**
* Represents the [Proof] which lead to this AtriumError.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package ch.tutteli.atrium.reporting.prerendering.text

import ch.tutteli.atrium.assertions.ExplanatoryAssertion
import ch.tutteli.atrium.creating.proofs.InvisibleFixedClaimGroup
import ch.tutteli.atrium.creating.proofs.InvisibleProofGroup
import ch.tutteli.atrium.creating.proofs.Proof
import ch.tutteli.atrium.reporting.reportables.Icon
import ch.tutteli.atrium.creating.proofs.ProofGroup
import ch.tutteli.atrium.reporting.Text
import ch.tutteli.atrium.reporting.reportables.Reportable
import ch.tutteli.atrium.reporting.reportables.ReportableGroup
import ch.tutteli.atrium.reporting.reportables.ReportableGroupWithDescription
import ch.tutteli.atrium.reporting.reportables.ReportableWithDesignation
import ch.tutteli.atrium.reporting.reportables.*
import ch.tutteli.atrium.reporting.theming.text.StyledString
import ch.tutteli.kbox.takeIf

Expand Down Expand Up @@ -144,6 +142,8 @@ fun determineChildControlObject(
} else
if (child.holds()) {
controlObject.copy(prefix = Icon.SUCCESS, indentLevel = indentLevel)
} else if (child is ProofGroup && child.hasAtLeastOneLeaveProof()) {
controlObject.copy(prefix = Icon.FAILING_GROUP, indentLevel = indentLevel)
} else {
controlObject.copy(prefix = Icon.FAILURE, indentLevel = indentLevel)
}
Expand All @@ -154,3 +154,23 @@ fun determineChildControlObject(
}
return newControlObject ?: controlObject.copy(prefix = childPrefix, indentLevel = indentLevel)
}

fun ReportableGroup.hasAtLeastOneLeaveProof(): Boolean =
this.children.any { child ->
run {
child is Proof &&
(child !is ProofGroup || (child !is InvisibleProofGroup && child !is InvisibleFixedClaimGroup || child.hasAtLeastOneLeaveProof()))
} || run {
child is FailureExplanationGroup && child.hasAtLeastOneLeaveProof()
} || run {
// if a child is a proof explanation, then we only want to show the flag in case the proof explanation
// contains a failure explanation, because the failure explanation might have a leave proof as well
// see CreateReportTest -> proofExplanation_withFailureExplanation for a case where a ProofExplanation
// contains a FailureExplanation but the FailureExplanation does not contain Proofs => i.e. don't use the
// flag
// see CreateReportTest -> proofExplanation_withFailureExplanationAndSubProofs_showsOnlyFailingProofs for
// a case where a ProofExplanation contains a FailureExplanation and it in turn contains a Proof
child is ProofExplanation && child.children.any { it is FailureExplanationGroup && it.hasAtLeastOneLeaveProof() }
}
}

Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package ch.tutteli.atrium.reporting.prerendering.text.impl

import ch.tutteli.atrium.reporting.theming.text.MonospaceLengthCalculator
import ch.tutteli.atrium.reporting.prerendering.text.TextPreRenderControlObject
import ch.tutteli.atrium.reporting.prerendering.text.OutputNode
import ch.tutteli.atrium.reporting.prerendering.text.TypedTextPreRenderer
import ch.tutteli.atrium.reporting.reportables.TextElement
import ch.tutteli.atrium.reporting.theming.text.noStyle

internal class DefaultTextElementTextPreRenderer : TypedTextPreRenderer<TextElement>(TextElement::class) {
internal class DefaultTextElementTextPreRenderer(
private val monospaceLengthCalculator: MonospaceLengthCalculator
) : TypedTextPreRenderer<TextElement>(TextElement::class) {
override fun transformIt(reportable: TextElement, controlObject: TextPreRenderControlObject): List<OutputNode> =
listOf(
OutputNode(
columns = listOf(reportable.string.noStyle(noLineBreak = false)),
columns = listOf(reportable.string.noStyle(monospaceLengthCalculator, noLineBreak = false)),
emptyList(),
definesOwnLevel = true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum class Icon : InlineElement {
DEBUG_INFO,
EMPTY_STRING,
FAILURE,
FAILING_GROUP,
FEATURE,
FEATURE_BULLET_POINT,
GROUPING_BULLET_POINT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ interface Reportable {
fun debugGroup(description: InlineElement, reportables: List<Reportable>): DebugGroup =
DefaultDebugGroup(description, reportables)

//TODO 1.3.0 remove?
fun inlineGroupOrSingleElement(inlineElements: List<InlineElement>): InlineElement =
takeIf(inlineElements.size == 1) {
inlineElements[0]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,51 @@
package ch.tutteli.atrium.reporting.text.impl

import ch.tutteli.atrium.core.polyfills.fullName
import ch.tutteli.atrium.reporting.LazyRepresentation
import ch.tutteli.atrium.reporting.ObjectFormatter
import ch.tutteli.atrium.reporting.Text
import ch.tutteli.atrium.reporting.theming.text.MonospaceLengthCalculator
import ch.tutteli.atrium.reporting.theming.text.impl.StringLengthMonospaceLengthCalculator
import ch.tutteli.atrium.reporting.reportables.TextElement
import ch.tutteli.atrium.reporting.text.TextObjFormatter
import ch.tutteli.atrium.reporting.theming.text.StyledString
import ch.tutteli.atrium.reporting.theming.text.TextStyler
import ch.tutteli.atrium.reporting.theming.text.noStyle
import kotlin.reflect.KClass

class DefaultTextObjFormatter(private val deprecatedObjectFormatter: ObjectFormatter) : TextObjFormatter {
class DefaultTextObjFormatter(
private val deprecatedObjectFormatter: ObjectFormatter,
private val monospaceLengthCalculator: MonospaceLengthCalculator
) : TextObjFormatter {
override fun format(value: Any?): StyledString =
when (value) {
null -> format(Text.NULL)
is Char -> "'$value'".noStyle()
is Boolean -> value.toString().noStyle()
//TODO 1.4.0 introduce different styles for different types, i.e. char, boolean, string etc. so that
// we have more like pretty printing in the output
is Char -> "\u200B'$value'".noStyle(monospaceLengthCalculator)
is Boolean -> value.toString().noStyle(StringLengthMonospaceLengthCalculator)

is Int,
is Long,
is Float,
is Double,
is Number -> value.toString().noStyle()
//TODO 1.4.0 format float, long, Date, etc. according to default locale specified in verb
is Number ->
//TODO 1.4.0 format float, long, Date, etc. according to default locale specified in verb
value.toString().noStyle(StringLengthMonospaceLengthCalculator)

is String -> formatString(value)

is TextElement -> value.string.noStyle(noLineBreak = false)
is TextElement -> value.string.noStyle(monospaceLengthCalculator, noLineBreak = false)
//TODO 1.3.0 we should be able to return multiple columns in this case
//TODO 1.4.0 introduce an Enum style
is Enum<*> -> (value.toString() + INDENT + "(" + (value::class.fullName) + ")").noStyle()
is Enum<*> -> (value.toString() + INDENT + "(" + (value::class.fullName) + ")").noStyle(
monospaceLengthCalculator
)

// Note, in theory a class name can contain any Unicode character on the JVM (even a zero-width space).
// We assume that no other chars than ascii letters are used and hence no need to calculate the
// monospaceLength
is Throwable -> value::class.fullName.noStyle(StringLengthMonospaceLengthCalculator)
else -> deprecatedObjectFormatter.format(value).noStyle(monospaceLengthCalculator, noLineBreak = false)

//TODO 1.4.0 introduce a Regex style
is Throwable -> value::class.fullName.noStyle()
else -> deprecatedObjectFormatter.format(value).noStyle(noLineBreak = false)
}

private fun limitRepresentation(value: String): String =
Expand All @@ -42,9 +56,9 @@ class DefaultTextObjFormatter(private val deprecatedObjectFormatter: ObjectForma
val s = "\"\"\"\n" +
(if (value.length > LIMIT) "${value.substring(0, LIMIT)}\n..." else value) + "\n" +
"\"\"\""
s.noStyle(noLineBreak = false)
s.noStyle(monospaceLengthCalculator, noLineBreak = false)
} else {
"\"${limitRepresentation(value)}\"".noStyle(noLineBreak = false)
"\"${limitRepresentation(value)}\"".noStyle(monospaceLengthCalculator, noLineBreak = false)
}

companion object {
Expand Down
Loading

0 comments on commit 63b14f8

Please sign in to comment.