C++: Fixed generic function false positive (#3043)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
diff --git a/components/prism-cpp.js b/components/prism-cpp.js
index 033eba6..cffefb0 100644
--- a/components/prism-cpp.js
+++ b/components/prism-cpp.js
@@ -61,7 +61,7 @@
Prism.languages.insertBefore('cpp', 'keyword', {
'generic-function': {
- pattern: /\b[a-z_]\w*\s*<(?:[^<>]|<(?:[^<>])*>)*>(?=\s*\()/i,
+ pattern: /\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,
inside: {
'function': /^\w+/,
'generic': {
diff --git a/components/prism-cpp.min.js b/components/prism-cpp.min.js
index 03920d5..ee85826 100644
--- a/components/prism-cpp.min.js
+++ b/components/prism-cpp.min.js
@@ -1 +1 @@
-!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!<keyword>)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(/<keyword>/g,function(){return t.source});e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!<keyword>)\\w+".replace(/<keyword>/g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:module|import)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"<mod-name>(?:\\s*:\\s*<mod-name>)?|:\\s*<mod-name>".replace(/<mod-name>/g,function(){return n})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b[a-z_]\w*\s*<(?:[^<>]|<(?:[^<>])*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism);
\ No newline at end of file
+!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!<keyword>)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(/<keyword>/g,function(){return t.source});e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!<keyword>)\\w+".replace(/<keyword>/g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:module|import)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"<mod-name>(?:\\s*:\\s*<mod-name>)?|:\\s*<mod-name>".replace(/<mod-name>/g,function(){return n})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism);
\ No newline at end of file
diff --git a/tests/languages/cpp/issue3042.test b/tests/languages/cpp/issue3042.test
new file mode 100644
index 0000000..ab5c47b
--- /dev/null
+++ b/tests/languages/cpp/issue3042.test
@@ -0,0 +1,126 @@
+class Foo
+{
+public:
+
+ friend bool operator== (const Foo& f1, const Foo& f2);
+ friend bool operator!= (const Foo& f1, const Foo& f2);
+
+ friend bool operator< (const Foo& f1, const Foo& f2);
+ friend bool operator> (const Foo& f1, const Foo& f2);
+
+ friend bool operator<= (const Foo& f1, const Foo& f2);
+ friend bool operator>= (const Foo& f1, const Foo& f2);
+};
+
+----------------------------------------------------
+
+[
+ ["keyword", "class"], ["class-name", "Foo"],
+ ["punctuation", "{"],
+ ["keyword", "public"], ["operator", ":"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "=="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "!="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "<"],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", ">"],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "<="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", ">="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["punctuation", "}"],
+ ["punctuation", ";"]
+]