From 2f86a79a80877635883e1a1bf10b2f35e71036ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Quenaudon?= Date: Mon, 20 Apr 2026 17:32:41 +0100 Subject: [PATCH] Avoid mixed slashes in Location --- .../com/squareup/wire/schema/Location.kt | 14 ++++- .../com/squareup/wire/schema/LocationTest.kt | 61 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 wire-schema/src/commonTest/kotlin/com/squareup/wire/schema/LocationTest.kt diff --git a/wire-schema/src/commonMain/kotlin/com/squareup/wire/schema/Location.kt b/wire-schema/src/commonMain/kotlin/com/squareup/wire/schema/Location.kt index ab04e34e71..fd27366c39 100644 --- a/wire-schema/src/commonMain/kotlin/com/squareup/wire/schema/Location.kt +++ b/wire-schema/src/commonMain/kotlin/com/squareup/wire/schema/Location.kt @@ -70,7 +70,19 @@ data class Location( base: String, path: String, ): Location { - return Location(base.trimEnd('/'), path, -1, -1) + return Location( + base = base.replace('\\', '/').trimEnd('/'), + path = if (path.length >= 3 && path[1] == ':' && path[2] == '\\') { + // Preserve the Windows drive root backslash (e.g. "C:\") since okio's path parser + // requires a backslash after the volume letter to recognize a Windows absolute path. + // TODO(Benoit) Remove this branch once https://github.com/square/okio/pull/1802 is released. + path.substring(0, 3) + path.substring(3).replace('\\', '/') + } else { + path.replace('\\', '/') + }, + line = -1, + column = -1, + ) } } } diff --git a/wire-schema/src/commonTest/kotlin/com/squareup/wire/schema/LocationTest.kt b/wire-schema/src/commonTest/kotlin/com/squareup/wire/schema/LocationTest.kt new file mode 100644 index 0000000000..e2300b8912 --- /dev/null +++ b/wire-schema/src/commonTest/kotlin/com/squareup/wire/schema/LocationTest.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2026 Square, Inc. + * + * 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 + * + * https://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 com.squareup.wire.schema + +import kotlin.test.Test +import kotlin.test.assertEquals + +class LocationTest { + @Test + fun getWithForwardSlashes() { + val location = Location.get("base/dir", "sub/file.proto") + assertEquals("base/dir", location.base) + assertEquals("sub/file.proto", location.path) + } + + @Test + fun getTrimsTrailingSlashFromBase() { + val location = Location.get("base/dir/", "file.proto") + assertEquals("base/dir", location.base) + } + + @Test + fun getNormalizesWindowsBackslashesInBase() { + val location = Location.get("C:\\Users\\username\\protos", "language\\language.proto") + assertEquals("C:/Users/username/protos", location.base) + assertEquals("language/language.proto", location.path) + } + + @Test + fun getNormalizesWindowsBackslashesInPath() { + val location = Location.get("", "language\\language.proto") + assertEquals("language/language.proto", location.path) + } + + @Test + fun getWithMixedSeparatorsInBase() { + val location = Location.get("C:\\Users/username\\protos/", "file.proto") + assertEquals("C:/Users/username/protos", location.base) + } + + @Test + fun getPreservesWindowsDriveRootBackslashInPath() { + // okio requires 'C:\' (backslash) to recognize Windows absolute paths; 'C:/' is not supported + // in older okio versions. Preserve the root backslash while converting internal separators. + val location = Location.get("", "C:\\Users\\protos") + assertEquals("C:\\Users/protos", location.path) + } +}