@@ -12,22 +12,22 @@ class Generic
1212 # NOTE: We also define this in the shim
1313 PARSER = const_defined? ( :RFC2396_PARSER ) ? RFC2396_PARSER : DEFAULT_PARSER
1414
15+ # This unsafe regex is the same one used in the URI::RFC2396_REGEXP class with the exception of the fact that we
16+ # do not include colon as a safe character. VS Code URIs always escape colons and we need to ensure we do the
17+ # same to avoid inconsistencies in our URIs, which are used to identify resources
18+ UNSAFE_REGEX = %r{[^\- _.!~*'()a-zA-Z\d ;/?@&=+$,\[ \] ]}
19+
1520 class << self
1621 #: (path: String, ?fragment: String?, ?scheme: String, ?load_path_entry: String?) -> URI::Generic
17- def from_path ( path :, fragment : nil , scheme : "file" , load_path_entry : nil )
18- # This unsafe regex is the same one used in the URI::RFC2396_REGEXP class with the exception of the fact that we
19- # do not include colon as a safe character. VS Code URIs always escape colons and we need to ensure we do the
20- # same to avoid inconsistencies in our URIs, which are used to identify resources
21- unsafe_regex = %r{[^\- _.!~*'()a-zA-Z\d ;/?@&=+$,\[ \] ]}
22-
22+ def from_win_path ( path :, fragment : nil , scheme : "file" , load_path_entry : nil )
2323 # On Windows, if the path begins with the disk name, we need to add a leading slash to make it a valid URI
2424 escaped_path = if /^[A-Z]:/i . match? ( path )
25- PARSER . escape ( "/#{ path } " , unsafe_regex )
25+ PARSER . escape ( "/#{ path } " , UNSAFE_REGEX )
2626 elsif path . start_with? ( "//?/" )
2727 # Some paths on Windows start with "//?/". This is a special prefix that allows for long file paths
28- PARSER . escape ( path . delete_prefix ( "//?" ) , unsafe_regex )
28+ PARSER . escape ( path . delete_prefix ( "//?" ) , UNSAFE_REGEX )
2929 else
30- PARSER . escape ( path , unsafe_regex )
30+ PARSER . escape ( path , UNSAFE_REGEX )
3131 end
3232
3333 uri = build ( scheme : scheme , path : escaped_path , fragment : fragment )
@@ -38,6 +38,21 @@ def from_path(path:, fragment: nil, scheme: "file", load_path_entry: nil)
3838
3939 uri
4040 end
41+
42+ #: (path: String, ?fragment: String?, ?scheme: String, ?load_path_entry: String?) -> URI::Generic
43+ def from_unix_path ( path :, fragment : nil , scheme : "file" , load_path_entry : nil )
44+ escaped_path = PARSER . escape ( path , UNSAFE_REGEX )
45+
46+ uri = build ( scheme : scheme , path : escaped_path , fragment : fragment )
47+
48+ if load_path_entry
49+ uri . require_path = path . delete_prefix ( "#{ load_path_entry } /" ) . delete_suffix ( ".rb" )
50+ end
51+
52+ uri
53+ end
54+
55+ alias_method :from_path , Gem . win_platform? ? :from_win_path : :from_unix_path
4156 end
4257
4358 #: String?
@@ -52,21 +67,37 @@ def add_require_path_from_load_entry(load_path_entry)
5267 end
5368
5469 #: -> String?
55- def to_standardized_path
70+ # On Windows, when we're getting the file system path back from the URI, we need to remove the leading forward
71+ # slash
72+ def to_standardized_win_path
5673 parsed_path = path
74+
5775 return unless parsed_path
5876
77+ # we can bail out parsing if there is nothing to unescape
78+ return parsed_path unless parsed_path . match? ( /%[0-9A-Fa-f]{2}/ )
79+
5980 unescaped_path = PARSER . unescape ( parsed_path )
6081
61- # On Windows, when we're getting the file system path back from the URI, we need to remove the leading forward
62- # slash
6382 if %r{^/[A-Z]:}i . match? ( unescaped_path )
6483 unescaped_path . delete_prefix ( "/" )
6584 else
6685 unescaped_path
6786 end
6887 end
6988
70- alias_method :full_path , :to_standardized_path
89+ #: -> String?
90+ def to_standardized_unix_path
91+ unescaped_path = path
92+ return unless unescaped_path
93+
94+ # we can bail out parsing if there is nothing to be unescaped
95+ return unescaped_path unless unescaped_path . match? ( /%[0-9A-Fa-f]{2}/ )
96+
97+ PARSER . unescape ( unescaped_path )
98+ end
99+
100+ alias_method :to_standardized_path , Gem . win_platform? ? :to_standardized_win_path : :to_standardized_unix_path
101+ alias_method :full_path , Gem . win_platform? ? :to_standardized_win_path : :to_standardized_unix_path
71102 end
72103end
0 commit comments