Formatting Regression in KtLint 1.4.1: Violates max_line_length and Reduces Readability

Expected Behavior
When formatting Kotlin code using KtLint 1.4.1, the formatter should produce output that respects the max_line_length setting defined in the .editorconfig file. Additionally, the formatted code should follow Kotlin Coding Conventions for readability, ensuring appropriate line breaks for long function calls.
For example, formatting this code:
@GskVersion4_14
public fun foreach(flags: PathForeachFlags, func: PathForeachFunc): Boolean = gsk_path_foreach(gskPathPointer.reinterpret(), flags.mask, PathForeachFuncFunc.reinterpret(), StableRef.create(func).asCPointer()).asBoolean()

with max_line_length=120 should produce this result, as in KtLint 1.3.1:
public fun foreach(
    flags: PathForeachFlags,
    func: PathForeachFunc,
): Boolean =
    gsk_path_foreach(
        gskPathPointer.reinterpret(),
        flags.mask,
        PathForeachFuncFunc.reinterpret(),
        StableRef.create(func).asCPointer()
    ).asBoolean()

This output is both more readable and adheres to the max_line_length constraint.
Observed Behavior
Using KtLint 1.4.1, the same input code is formatted as:
public fun foreach(
    flags: PathForeachFlags,
    func: PathForeachFunc,
): Boolean = gsk_path_foreach(gskPathPointer.reinterpret(), flags.mask, PathForeachFuncFunc.reinterpret(), StableRef.create(func).asCPointer()).asBoolean()

This output violates the max_line_length constraint and reduces readability.
Steps to Reproduce

Prepare a .editorconfig file with the following configuration: .editorconfig
Use KtLint 1.4.1 to format the following code snippet:@GskVersion4_14
public fun foreach(flags: PathForeachFlags, func: PathForeachFunc): Boolean = gsk_path_foreach(gskPathPointer.reinterpret(), flags.mask, PathForeachFuncFunc.reinterpret(), StableRef.create(func).asCPointer()).asBoolean()

Compare the output of KtLint 1.4.1 to the output of KtLint 1.3.1 or the expected result above.

Command executed:

import com.pinterest.ktlint.cli.ruleset.core.api.RuleSetProviderV3
import com.pinterest.ktlint.rule.engine.api.Code
import com.pinterest.ktlint.rule.engine.api.EditorConfigDefaults
import com.pinterest.ktlint.rule.engine.api.EditorConfigDefaults.Companion.load
import com.pinterest.ktlint.rule.engine.api.KtLintRuleEngine
import com.pinterest.ktlint.rule.engine.core.api.AutocorrectDecision
import com.pinterest.ktlint.rule.engine.core.api.propertyTypes
import org.gtkkn.gir.log.logger
import java.io.File
import java.nio.file.Path
import java.util.ServiceLoader

class KtLintFormatter(outputDir: File) {
    private val ruleProviders = buildSet {
        ServiceLoader.load(RuleSetProviderV3::class.java).flatMapTo(this) { it.getRuleProviders() }
    }
    private val ktLintRuleEngine: KtLintRuleEngine

    init {
        val editorConfigPath = findEditorConfigPath(outputDir)
        if (editorConfigPath == null) {
            logger.error { "Unable to find .editorconfig file in or above directory ${outputDir.absolutePath}" }
        }
        ktLintRuleEngine = KtLintRuleEngine(
            ruleProviders = ruleProviders,
            editorConfigDefaults = editorConfigPath?.let { load(it, ruleProviders.propertyTypes()) }
                ?: EditorConfigDefaults.EMPTY_EDITOR_CONFIG_DEFAULTS,
        )
    }

    fun formatAndWriteKotlinFile(
        outputDirectory: File,
        packageName: String,
        simpleName: String,
        content: String
    ) {
        // Create the package directory structure
        val packageDir = packageName.replace(".", "/")
        val dir = File(outputDirectory, packageDir).apply { mkdirs() }

        // Create the Kotlin file
        val kotlinFile = File(dir, "$simpleName.kt")
        kotlinFile.createNewFile()

        // Format and write the file
        kotlinFile.writeText(
            ktLintRuleEngine.format(Code.fromSnippet(content)) { _ ->
                AutocorrectDecision.ALLOW_AUTOCORRECT
            },
        )
    }

    private fun findEditorConfigPath(startDir: File): Path? {
        var currentDir: File? = startDir

        while (currentDir != null) {
            val editorConfig = File(currentDir, ".editorconfig")
            if (editorConfig.exists()) {
                return editorConfig.toPath()
            }

            currentDir = currentDir.parentFile
        }

        return null
    }
}

Your Environment

Version of ktlint used: 1.4.1
Relevant .editorconfig settings:[*.{kt,kts}]
max_line_length = 120

Integration method: Custom task using KtLintRuleEngine directly.
Operating System and version: Ubuntu 24.04

You call the KtLintRuleEngine incorrectly:
ktLintRuleEngine.format(Code.fromSnippet(content))

You have provide a code snippet without providing its virtual path. As of that ktlint can not locate the proper .editorconfig file. Instead of fromSnippet use fromSnippetWithPath. The provide virtualPath to this snippet should be in the same directory, or a subdirectory of the directory where your .editorconfig is located.

Thank you for your suggestion. I updated my code to use Code.fromSnippetWithPath, ensuring the virtualPath points to the generated file's location. Here are the changes I made:
// Provide a virtual path for the code snippet as a Path
val virtualPath = kotlinFile.toPath()

// Format and write the file
kotlinFile.writeText(
    ktLintRuleEngine.format(Code.fromSnippetWithPath(content, virtualPath)) { _ ->
        AutocorrectDecision.ALLOW_AUTOCORRECT
    },
)

The .editorconfig file is located at the root of the project, and the virtualPath points to a subdirectory of the root, as seen in this file:  [AboutDialog.kt](https://gitlab.com/gtk-kn/gtk-kn/-/blob/master/bindings/adwaita/src/nativeMain/kotlin/org/gtkkn/bindings/adw/AboutDialog.kt?ref_type=heads#L1353).
However, the formatting behavior remains inconsistent with version 1.3.1.

Do you have any other suggestions to resolve this issue?

Suggestions:

Double check the virtualPath.
Add the root = true property in .editorconfig (https://editorconfig.org/)
Use ktlint-gradle instead of your custom plugin, or look at how they call KtlintRuleEngine

Unfortunate virtualPath is absolute, the root = true is there. The Gradle plugin is not an option. I just don't get why this works fine with 1.3.1 but not 1.4.1...

I just don't get why this works fine with 1.3.1 but not 1.4.1...

I have no clue why it breaks. When I use your .editorconfig and provided code sample, then Ktlint CLI produces the expected results.
It would be helpful if you can enable debug logging for ktlint, or set a breakpoint at this line and inspect the result.

Sure, I'm happy to help debugging this issue, just let me know what else can I do to help (I'm also available if you want to have a remote debug session in a call).
This is how it looks on 1.3.1:

as you can see, filePath is null, but editorConfigDefaults contains the correct rules, I guess because of this:
    init {
        val editorConfigPath = findEditorConfigPath(outputDir)
        if (editorConfigPath == null) {
            logger.error { "Unable to find .editorconfig file in or above directory ${outputDir.absolutePath}" }
        }
        ktLintRuleEngine = KtLintRuleEngine(
            ruleProviders = ruleProviders,
            editorConfigDefaults = editorConfigPath?.let { load(it, ruleProviders.propertyTypes()) }
                ?: EditorConfigDefaults.EMPTY_EDITOR_CONFIG_DEFAULTS,
        )
    }

Version 1.4.1 looks more or less the same:

The .editorconfig path is /home/rleinardi/Workspace/My/gtk-kn/.editorconfig', not sure if it's normal that has been detected as /home/rleinardi/Workspace/My/gtk-kn/gir/./.kt, could this be the issue? giris the module that is running KtLint, but the.editorconfigis in the root of the project. But in any case, sinceeditorConfigDefaults` contains all the rules, shouldn't this be enough for 1.4.1? I still don't get why the difference in formatting from 1.3.1, since they seem to have the same configuration.
Please let me know if I can provide other details that can help with this issue.

I have identified the problem. You have disabled ktlint_standard_max-line-length rule. As of that rules no longer respect the max_line_length property. This was an intended change which should have been more clearly documented in the changelog.

@paul-dingemans thank you! I can confirm that after removing ktlint_standard_max-line-length now 1.4.1 respects the max-line-length! I don't even remember why I had it disabled.
But there is still 1 final difference between 1.3.1 and 1.4.1: the latter uses a different spacing for the callback parameters than 1.3.1 and the formatter used by Intellij IDEA:

Is there a setting that I can change to restore the same spacing that 1.3.1 and IDEA have?

No, this behavior is determined by the ktlint_code_style setting. See #2816 for more information.


Fix proptypes deprecation issue.

PropTypes has been moved to a separate package.

Could you push a new release with this fix?


SPIR-V/OpenCL & sycl::reduce_over_group

I've been trying AdaptiveCpp's generic compilation flow for spir-v/opencl targets (intel CPU/GPU) on a SYCL program with a kernel invoking sycl::reduce_over_group.  Un-commenting the line at https://github.com/AdaptiveCpp/AdaptiveCpp/blob/v23.10.0/src/runtime/ocl/ocl_queue.cpp#L453 lifts  the RequiresExtension error related to the  SPV_EXT_shader_atomic_float_add not being enabled by default, but results in the following being unresolved :
float hipsycl::sycl::detail::sscp_builtins::__hipsycl_reduce_over_group<float, hipsycl::sycl::plus<float> >(hipsycl::sycl::sub_group, float, hipsycl::sycl::plus<float>)
So I was wondering if this is an expected behavior of the __hipsycl_reduce_over_group for SPIR-V/OpenCL flow or if I'm missing something?

Noted thanks a lot for confirming that!


503 Restricted Network error when importing attachments

I just tried an import via WP-CLI within the web container on a wp-local-docker instance and noted that the attachment import phase was failing with "Failed to import Media" errors for every item. After eliminating some other I attempted to download one of the attachments hosted on the current live site using curl -I http://... and got a HTTP/1.0 503 Restricted Network result.
I made sure that I didn't have any network  level configuration in place that would block outgoing connections from the container, and the same request works fine from the macOS terminal. Oddly, the behavior is inconsistent, and happens for some URLs and not others, and sometimes differs between an SSL and non-SSL access of the same image/attachment. Here's one with a random image found on the web that consistently fails for me:
# curl -I http://s3.amazonaws.com/libapps/accounts/8825/images/shutterstock_130209515.jpg
HTTP/1.0 503 Restricted Network
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 19363

while this (SSL version of same file) consistently works:
# curl -I https://s3.amazonaws.com/libapps/accounts/8825/images/shutterstock_130209515.jpg
HTTP/1.1 200 OK
x-amz-id-2: cON2D0nLMToEKkEglIIVuAURmZhn8WoHKFmbyenP9CZSBpcZqPZRqPh0UBowCKHwFZnZFCg41Ec=
x-amz-request-id: C9C4E618A29DA5A8
Date: Fri, 25 Aug 2017 15:27:08 GMT
Last-Modified: Wed, 17 Jun 2015 18:21:42 GMT
ETag: "2982a6d99d33b3ff2a9044dc8355bee1"
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2354005
Server: AmazonS3

My understanding is that a given Docker container might be configured to allow some kinds of outbound network connections and not others. Is it possible there's an issue in how the web container is set up that could be causing this? Any suggestions for further troubleshooting?

Hmmm, not sure on this one. I just ran that curl command successfully from within a container. My guess is either a Docker or network level issue.

Going to close this since it has been inactive for a while. If this is still happening with the latest images available on dockerhub and the latest version of wp-local-docker, please provide more details on your OS and any steps I can use to replicate.


some files don't work anyome

What version of Music Assistant has the issue?
2.0.0b78
The problem
Some mp3 files that used to play fine no longer work
How to reproduce
Download https://www.gstatic.com/voice_delight/sounds/long/rain.mp3 and try to play it

Relevant log output
File "/usr/local/lib/python3.11/site-packages/music_assistant/server/controllers/player_queues.py", line 197, in play_media
raise MediaNotFoundError(f"Invalid uri: {item}") from err
music_assistant.common.models.errors.MediaNotFoundError: Invalid uri: filesystem_local://track/wav/rain_3600.mp3
Additional information
No response
What version of Home Assistant Core are your running
2023.12.1
What type of installation are you running?
Home Assistant Container
On what type of hardware are you running?
Linux

Do all the other files in that folder play ok?

No. Some files play okay and some files do not. These are all files that
used to work perfectly fine, and still work fine on my computers. I pointed
to one that you can download to test.
On Sun, Dec 10, 2023, 12:58 PM OzGav @.***> wrote:

Do all the other files in that folder play ok?
—
Reply to this email directly, view it on GitHub
https://github.com/music-assistant/hass-music-assistant/issues/1684#issuecomment-1849082643,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN7SXNRXK4MMYMGGYDN26LYIYO6LAVCNFSM6AAAAABAOZYLXGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNBZGA4DENRUGM
.
You are receiving this because you authored the thread.Message ID:
@.***>

Can you see any pattern to which ones are working and which ones aren’t. For example, do all the ones that don’t work have the underscore in the file name?

No, I cannot identify a pattern. I tried changing the file names and that
made no difference. Does the rain file from the link I provided work for
you?
On Sun, Dec 10, 2023, 4:16 PM OzGav @.***> wrote:

Can you see any pattern to which ones are working and which ones aren’t.
For example, do all the ones that don’t work have the underscore in the
file name?
—
Reply to this email directly, view it on GitHub
https://github.com/music-assistant/hass-music-assistant/issues/1684#issuecomment-1849142267,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN7SXI4M5BRAJKWKRMDB5DYIZGFZAVCNFSM6AAAAABAOZYLXGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNBZGE2DEMRWG4
.
You are receiving this because you authored the thread.Message ID:
@.***>

No I haven’t tried it but the error is saying that MA can’t find the file. Do you have those few files added via a different provider or are they just a sub folder of all your other music?

all the files, the ones that work and the ones that do not, are added in
the same way. And all of those files used to work fine.
On Sun, Dec 10, 2023 at 6:09 PM OzGav @.***> wrote:

No I haven’t tried it but the error is saying that MA can’t find the file.
Do you have those few files added via a different provider or are they just
a sub folder of all your other music?
—
Reply to this email directly, view it on GitHub
https://github.com/music-assistant/hass-music-assistant/issues/1684#issuecomment-1849214804,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN7SXOTJNWPCPKOAN4CTADYIZTONAVCNFSM6AAAAABAOZYLXGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNBZGIYTIOBQGQ
.
You are receiving this because you authored the thread.Message ID:
@.***>

Ok give me some time to try and recreate the problem.


Add configuring webhook

Add configuring webhook

Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 100.00%. Comparing base (060d018) to head (b398824).

Additional details and impacted files
@@            Coverage Diff            @@
##              main       #23   +/-   ##
=========================================
  Coverage   100.00%   100.00%
=========================================
  Files            4         4
  Lines          167       169    +2
  Branches         3         3
=========================================
+ Hits           167       169    +2

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.


Icons

Added icon object to current and 10 day

Looks good from what I can see! We can definitely refactor what we both worked on once we’re together but it all looks really solid!


(on event page) Link GUI "total events" "total errors" to values in event class

QTextEdit is probably not the best solution for displaying this data as currently implemented

Link update commands

resolved with commit 98d1136


Row Major -> Column Major

It's unfortunate, but Fibers need to be column major to match other arrays in the language so that operations that require concordant iteration (like Broadcast) can be efficient by default. This actually isn't all that difficult, but it does need to happen.

One potential problem resulting from this is that we can no longer read off the dimensions of a fiber from it's constructor:
@fiber d(10, sl(20, e(0))) used to be a 10x20 csr matrix, but would now be a 20x10 csc matrix (the order of modes is backwards). Column major was a mistake for Julia tbh.

One way to fix the dimension problem is to add the sublevel as the first argument of level constructors. Then we have:
Fiber d(sl(e(0.0), 20), 10) which would be a 20 x 10 matrix. This would also make the constructors simpler.

Column Major Pros:

Pointwise operations are concordant by default
@fiber d(sl(e(0.0), 20), 10) puts the format names first and dimensions second, analogous to Array{T, N}(undef, 20, 10) which puts initializer first and dimensions second
Column Major Cons:
My research group will be confused because they are all row major
The vector of subarrays analogy is less obvious. If A[i, j, k] is a column major vector of vectors, we have to write it A[k][i, j], whereas if it was row major we write A[i][j, k].

Of course we can always add permutation wrappers, etc to support one or the other but the question here is what is the default for the fiber type that we are introducing?


[WIP] Opaque result types prototype

WIP towards a prototype of an MVP subset of https://forums.swift.org/t/opaque-result-types/15645 . For an initial implementation, this won't include the resilience, second-order where constraint, or multiple conditional conformance features proposed in the thread.

[x] Parsing
[x] Decl representation for opaque types
[x] Type representation for opaque types (probably as some new kind of ArchetypeType?)
[x] Type checking to resolve the underlying type of opaque types
[x] Non-resilient SILGen (lowering the opaque type directly to its underlying type)
[x] Serialization support

Limitations include:

The opaque type is spelled __opaque Protocol or __opaque ProtocolA & ProtocolB [& ProtocolC...] as placeholder spelling.
Opaque types can only appear as the return type of func declarations, not properties or closures.
where clause constraints on the opaque type are not yet supported, nor are conditional conformances on the opaque type. However, the protocols in the __opaque type can be arbitrary protocols, with any number of associated type or Self type requirements. __opaque types can in turn be inferred as associated types of protocol conformances.
The runtime and resilience aspects are not yet implemented. Changing the underlying type of a public opaque type will break ABI.

Some known issues:

Because of the missing runtime support, I substitute out opaque types during SILGen in a rather hacky unprincipled way. It's likely that the optimizer, particularly generic specialization, may still cause crashes.
The type checker currently crashes if there's a type error in the underlying type, such as if it does not conform to the required protocols.
Diagnostics involving opaque types will print the type with a compiler-internal representation involving the original decl name and generic arguments, instead of anything human-understandable.

@swift-ci Please build toolchain macOS platform

macOS Toolchain
Download Toolchain
Git Sha - b63ccda2dc419f372bf4d37bc7b4b8e32d137347
Install command
tar -zxf  swift-PR-21137-216-osx.tar.gz --directory ~/

The real implementation
https://github.com/apple/swift/pull/22072 can do everything this can now.