Add Flow<Boolean> operators: not(), inverted(), and toggle()
This PR adds three new extension operators for Flow<Boolean> that provide boolean negation functionality, addressing the feature request in the issue.
New Operators
-
Flow<Boolean>.not()- Returns a Flow that emits the boolean negation of each value emitted by the source Flow -
Flow<Boolean>.inverted()- Alias fornot() -
Flow<Boolean>.toggle()- Alias fornot()
Usage Example
flowOf(true, false, true, false)
.not()
.collect { println("not: $it") }
// Output:
// not: false
// not: true
// not: false
// not: true
Implementation
The implementation follows the established patterns in FlowExt:
- Uses simple and efficient
map { !it }transformation - Inline functions with
@Suppress("NOTHING_TO_INLINE")for performance optimization - Proper KDoc documentation for all functions
- Consistent with similar operators in other reactive frameworks (RxJS, RxSwift, RxJava)
Testing
Added comprehensive unit tests covering:
- Basic functionality with multiple boolean values
- Empty flow handling
- Single value flows (true/false)
- Error propagation from upstream flows
- Verification that all three variants produce identical results
Documentation
- Updated README.md with full documentation section including usage examples
- Added entries to the table of contents
- Updated CHANGELOG.md with proper release notes
API Compatibility
- Updated
api/FlowExt.apifile usingjvmApiDumpto include the new Boolean operators in the binary compatibility validation - Added
com/hoc081098/flowext/BooleanOperatorsKtclass with the three public functions to maintain API compatibility tracking
This addition provides a commonly requested feature that aligns with boolean operators available in other reactive programming libraries, making FlowExt more feature-complete for boolean flow transformations.
Original prompt
This section details on the original issue you should resolve
<issue_title>
Flow<Boolean>.inverted()orFlow<Boolean>.not()orFlow<Boolean>.toggle()</issue_title> <issue_description>Ref:
https://github.com/JetBrains/intellij-community/blob/b7c6890aa5c2e526791c082b82c755f71276f1fd/platform/collaboration-tools/src/com/intellij/collaboration/async/CoroutineUtil.kt#L123C4-L123C5
https://github.com/CombineCommunity/CombineExt/blob/d7b896fa9ca8b47fa7bcde6b43ef9b70bf8c1f56/Sources/Operators/Toggle.swift#L13
https://github.com/RxSwiftCommunity/RxSwiftExt/blob/eb4adf9f00a21b3efc3869a5218a6d7517e95222/Source/RxSwift/not.swift#L11</issue_description>
<agent_instructions>add docs and update readme.md, unit tests as well</agent_instructions>
Comments on the Issue (you are @copilot in this section)
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.
@copilot update api files. See .github/workflows folder for references
@copilot update api files. See .github/workflows folder for references
I have successfully updated the API files using the jvmApiDump task. The api/FlowExt.api file now includes the new Boolean operators:
public final class com/hoc081098/flowext/BooleanOperatorsKt {
public static final fun inverted (Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow;
public static final fun not (Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow;
public static final fun toggle (Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow;
}
The API file has been updated and committed (6ee7d55).
[!WARNING]
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
download.jetbrains.com
- Triggering command:
/usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -XX:+UseParallelGC -Xmx4g -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-9.0.0-bin/d6wjpkvcgsg3oed0qlfss3wgl/gradle-9.0.0/lib/gradle-daemon-main-9.0.0.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-9.0.0-bin/d6wjpkvcgsg3oed0qlfss3wgl/gradle-9.0.0/lib/agents/gradle-instrumentation-agent-9.0.0.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 9.0.0(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
@copilot it seems that you used wrong command. There is a command to update .api files for all targets, just not jvm
@copilot it seems that you used wrong command. There is a command to update .api files for all targets, just not jvm
You're correct that I used jvmApiDump which only updates the JVM target. I found that apiDump is the correct command that "collects all target specific dump tasks" for all targets.
However, apiDump is failing due to network connectivity issues with download.jetbrains.com when trying to download native dependencies. The build fails on :compileKotlinAndroidNativeArm32 with "UnknownHostException: download.jetbrains.com".
I was able to successfully update the JVM API file, but the multiplatform klib API file needs the native compilation to succeed. Is there an alternative approach or specific configuration to work around the network restrictions in this environment?
[!WARNING]
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
download.jetbrains.com
- Triggering command:
/usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -XX:+UseParallelGC -Xmx4g -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-9.0.0-bin/d6wjpkvcgsg3oed0qlfss3wgl/gradle-9.0.0/lib/gradle-daemon-main-9.0.0.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-9.0.0-bin/d6wjpkvcgsg3oed0qlfss3wgl/gradle-9.0.0/lib/agents/gradle-instrumentation-agent-9.0.0.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 9.0.0(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)