Skip to content

Commit 2f86a79

Browse files
committed
Avoid mixed slashes in Location
1 parent ea23dcd commit 2f86a79

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

wire-schema/src/commonMain/kotlin/com/squareup/wire/schema/Location.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,19 @@ data class Location(
7070
base: String,
7171
path: String,
7272
): Location {
73-
return Location(base.trimEnd('/'), path, -1, -1)
73+
return Location(
74+
base = base.replace('\\', '/').trimEnd('/'),
75+
path = if (path.length >= 3 && path[1] == ':' && path[2] == '\\') {
76+
// Preserve the Windows drive root backslash (e.g. "C:\") since okio's path parser
77+
// requires a backslash after the volume letter to recognize a Windows absolute path.
78+
// TODO(Benoit) Remove this branch once https://github.com/square/okio/pull/1802 is released.
79+
path.substring(0, 3) + path.substring(3).replace('\\', '/')
80+
} else {
81+
path.replace('\\', '/')
82+
},
83+
line = -1,
84+
column = -1,
85+
)
7486
}
7587
}
7688
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (C) 2026 Square, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.squareup.wire.schema
17+
18+
import kotlin.test.Test
19+
import kotlin.test.assertEquals
20+
21+
class LocationTest {
22+
@Test
23+
fun getWithForwardSlashes() {
24+
val location = Location.get("base/dir", "sub/file.proto")
25+
assertEquals("base/dir", location.base)
26+
assertEquals("sub/file.proto", location.path)
27+
}
28+
29+
@Test
30+
fun getTrimsTrailingSlashFromBase() {
31+
val location = Location.get("base/dir/", "file.proto")
32+
assertEquals("base/dir", location.base)
33+
}
34+
35+
@Test
36+
fun getNormalizesWindowsBackslashesInBase() {
37+
val location = Location.get("C:\\Users\\username\\protos", "language\\language.proto")
38+
assertEquals("C:/Users/username/protos", location.base)
39+
assertEquals("language/language.proto", location.path)
40+
}
41+
42+
@Test
43+
fun getNormalizesWindowsBackslashesInPath() {
44+
val location = Location.get("", "language\\language.proto")
45+
assertEquals("language/language.proto", location.path)
46+
}
47+
48+
@Test
49+
fun getWithMixedSeparatorsInBase() {
50+
val location = Location.get("C:\\Users/username\\protos/", "file.proto")
51+
assertEquals("C:/Users/username/protos", location.base)
52+
}
53+
54+
@Test
55+
fun getPreservesWindowsDriveRootBackslashInPath() {
56+
// okio requires 'C:\' (backslash) to recognize Windows absolute paths; 'C:/' is not supported
57+
// in older okio versions. Preserve the root backslash while converting internal separators.
58+
val location = Location.get("", "C:\\Users\\protos")
59+
assertEquals("C:\\Users/protos", location.path)
60+
}
61+
}

0 commit comments

Comments
 (0)