aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsigmaSd <bedisnbiba@gmail.com>2022-08-24 07:38:06 +0100
committerGitHub <noreply@github.com>2022-08-23 23:38:06 -0700
commita4e4609d62c38b7b949e5c8079dfa5f10803bdcd (patch)
tree0013889ba8fdc091d8173b3806e2ecdbc9213163
parent9a100ee169f80cbfe45872939ed9b4f70f6bfe3f (diff)
downloadrneovim-a4e4609d62c38b7b949e5c8079dfa5f10803bdcd.tar.gz
rneovim-a4e4609d62c38b7b949e5c8079dfa5f10803bdcd.tar.bz2
rneovim-a4e4609d62c38b7b949e5c8079dfa5f10803bdcd.zip
fix(path): path_is_url returns false for "foo:/" #19797
Problem: path_to_url() returns false for single-slash URIs ("foo:/" vs "foo://"). This is not compliant with the URI spec. https://url.spec.whatwg.org/#url-representation LSP in particular allows single-slash URIs. Solution: Relax path_to_url() to accept single-slash URIs. This is not fully compliant (only ":" is required by the spec), but it is hopefully good enough without causing false-positives in typical text files. ref https://url.spec.whatwg.org/#windows-drive-letter ref https://github.com/neovim/neovim/pull/19773 ref https://github.com/neovim/neovim/pull/19773#issuecomment-1214763769
-rw-r--r--src/nvim/path.c26
-rw-r--r--src/nvim/window.c2
-rw-r--r--test/unit/path_spec.lua4
3 files changed, 27 insertions, 5 deletions
diff --git a/src/nvim/path.c b/src/nvim/path.c
index d50ef87b62..ce0a7fb281 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -33,7 +33,7 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-#define URL_SLASH 1 // path_is_url() has found "://"
+#define URL_SLASH 1 // path_is_url() has found ":/"
#define URL_BACKSLASH 2 // path_is_url() has found ":\\"
#ifdef gen_expand_wildcards
@@ -1751,12 +1751,26 @@ char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count,
return file_name;
}
-// Check if the "://" of a URL is at the pointer, return URL_SLASH.
+/// Checks for a Windows drive letter ("C:/") at the start of the path.
+///
+/// @see https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
+bool path_has_drive_letter(const char *p)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return strlen(p) >= 2
+ && ASCII_ISALPHA(p[0])
+ && (p[1] == ':' || p[1] == '|')
+ && (strlen(p) == 2 || ((p[2] == '/') | (p[2] == '\\') | (p[2] == '?') | (p[2] == '#')));
+}
+
+// Check if the ":/" of a URL is at the pointer, return URL_SLASH.
// Also check for ":\\", which MS Internet Explorer accepts, return
// URL_BACKSLASH.
int path_is_url(const char *p)
{
- if (strncmp(p, "://", 3) == 0) {
+ // In the spec ':' is enough to recognize a scheme
+ // https://url.spec.whatwg.org/#scheme-state
+ if (strncmp(p, ":/", 2) == 0) {
return URL_SLASH;
} else if (strncmp(p, ":\\\\", 3) == 0) {
return URL_BACKSLASH;
@@ -1781,6 +1795,10 @@ int path_with_url(const char *fname)
return 0;
}
+ if (path_has_drive_letter(fname)) {
+ return 0;
+ }
+
// check body: alpha or dash
for (p = fname + 1; (isalpha(*p) || (*p == '-')); p++) {}
@@ -1789,7 +1807,7 @@ int path_with_url(const char *fname)
return 0;
}
- // "://" or ":\\" must follow
+ // ":/" or ":\\" must follow
return path_is_url(p);
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 89611177f9..7ad5e49d2f 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -6582,7 +6582,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
/*
* Search forward for the last char of the file name.
- * Also allow "://" when ':' is not in 'isfname'.
+ * Also allow ":/" when ':' is not in 'isfname'.
*/
len = 0;
while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index fb476397e6..eb23a3cff1 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -640,6 +640,10 @@ describe('path.c', function()
eq(2, path_with_url([[test-abc:\\xyz\foo\b3]]))
eq(0, path_with_url([[-test://xyz/foo/b4]]))
eq(0, path_with_url([[test-://xyz/foo/b5]]))
+ eq(1, path_with_url([[test-C:/xyz/foo/b5]]))
+ eq(1, path_with_url([[test-custom:/xyz/foo/b5]]))
+ eq(0, path_with_url([[c:/xyz/foo/b5]]))
+ eq(0, path_with_url([[C:/xyz/foo/b5]]))
end)
end)
end)