From 5de8947f15cecf5f0496ecbe9ec7c68441665a45 Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Wed, 1 Sep 2021 14:04:46 +0200 Subject: [PATCH] C++: Fixed generic function false positive (#3043) --- components/prism-cpp.js | 2 +- components/prism-cpp.min.js | 2 +- tests/languages/cpp/issue3042.test | 126 +++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 tests/languages/cpp/issue3042.test diff --git a/components/prism-cpp.js b/components/prism-cpp.js index 033eba6f37..cffefb0c49 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 03920d5346..ee8582639d 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(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,function(){return t.source});e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//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]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//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(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,function(){return t.source});e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//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]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//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 0000000000..ab5c47b4df --- /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", ";"] +]