diff --git a/CHANGES.md b/CHANGES.md
index 7e3e82de81..cdf11535de 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -19,6 +19,10 @@ Language Improvements:
- (ini) support TOML arrays, clean up grammar (#2335) [Josh Goebel][]
- (vbnet) add nameof operator to the keywords (#2329) [Youssef Victor][]
- (stan) updated with improved coverage of language keywords and patterns. (#1829) [Jeffrey Arnold][]
+- enh(cpp) Detect namespaced function types (`A::typeName func(...)`) (#2332) [Josh Goebel][]
+- enh(cpp) Detect namespaced functions also (`A::functionName`) (#2332) [Josh Goebel][]
+- enh(cpp) Properly detect decltype(auto) (#2332) [Josh Goebel][]
+- enh(cpp) recognize primitive types (`int8_t`, etc.) as function types (#2332) [Josh Goebel][]
Developer Tools:
diff --git a/src/languages/cpp.js b/src/languages/cpp.js
index 38a0335a18..a6849e47cb 100644
--- a/src/languages/cpp.js
+++ b/src/languages/cpp.js
@@ -7,6 +7,16 @@ Website: https://isocpp.org
*/
function(hljs) {
+ function optional(s) {
+ return '(?:' + s + ')?';
+ }
+ var DECLTYPE_AUTO_RE = 'decltype\\(auto\\)'
+ var NAMESPACE_RE = '[a-zA-Z_]\\w*::'
+ var TEMPLATE_ARGUMENT_RE = '<.*?>';
+ var FUNCTION_TYPE_RE = '(' +
+ DECLTYPE_AUTO_RE + '|' +
+ optional(NAMESPACE_RE) +'[a-zA-Z_]\\w*' + optional(TEMPLATE_ARGUMENT_RE) +
+ ')';
var CPP_PRIMITIVE_TYPES = {
className: 'keyword',
begin: '\\b[a-z\\d_]*_t\\b'
@@ -64,7 +74,13 @@ function(hljs) {
]
};
- var FUNCTION_TITLE = hljs.IDENT_RE + '\\s*\\(';
+ var TITLE_MODE = {
+ className: 'title',
+ begin: optional(NAMESPACE_RE) + hljs.IDENT_RE,
+ relevance: 0
+ };
+
+ var FUNCTION_TITLE = optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';
var CPP_KEYWORDS = {
keyword: 'int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof ' +
@@ -99,86 +115,99 @@ function(hljs) {
STRINGS
];
- return {
- aliases: ['c', 'cc', 'h', 'c++', 'h++', 'hpp', 'hh', 'hxx', 'cxx'],
+ var EXPRESSION_CONTEXT = {
+ // This mode covers expression context where we can't expect a function
+ // definition and shouldn't highlight anything that looks like one:
+ // `return some()`, `else if()`, `(x*sum(1, 2))`
+ variants: [
+ {begin: /=/, end: /;/},
+ {begin: /\(/, end: /\)/},
+ {beginKeywords: 'new throw return else', end: /;/}
+ ],
keywords: CPP_KEYWORDS,
- illegal: '',
contains: EXPRESSION_CONTAINS.concat([
- PREPROCESSOR,
{
- begin: '\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<', end: '>',
+ begin: /\(/, end: /\)/,
keywords: CPP_KEYWORDS,
- contains: ['self', CPP_PRIMITIVE_TYPES]
- },
- {
- begin: hljs.IDENT_RE + '::',
- keywords: CPP_KEYWORDS
+ contains: EXPRESSION_CONTAINS.concat(['self']),
+ relevance: 0
+ }
+ ]),
+ relevance: 0
+ };
+
+ var FUNCTION_DECLARATION = {
+ className: 'function',
+ begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
+ returnBegin: true, end: /[{;=]/,
+ excludeEnd: true,
+ keywords: CPP_KEYWORDS,
+ illegal: /[^\w\s\*&:<>]/,
+ contains: [
+
+ { // to prevent it from being confused as the function title
+ begin: DECLTYPE_AUTO_RE,
+ keywords: CPP_KEYWORDS,
+ relevance: 0,
},
{
- // This mode covers expression context where we can't expect a function
- // definition and shouldn't highlight anything that looks like one:
- // `return some()`, `else if()`, `(x*sum(1, 2))`
- variants: [
- {begin: /=/, end: /;/},
- {begin: /\(/, end: /\)/},
- {beginKeywords: 'new throw return else', end: /;/}
- ],
- keywords: CPP_KEYWORDS,
- contains: EXPRESSION_CONTAINS.concat([
- {
- begin: /\(/, end: /\)/,
- keywords: CPP_KEYWORDS,
- contains: EXPRESSION_CONTAINS.concat(['self']),
- relevance: 0
- }
- ]),
+ begin: FUNCTION_TITLE, returnBegin: true,
+ contains: [TITLE_MODE],
relevance: 0
},
{
- className: 'function',
- begin: '(' + hljs.IDENT_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
- returnBegin: true, end: /[{;=]/,
- excludeEnd: true,
+ className: 'params',
+ begin: /\(/, end: /\)/,
keywords: CPP_KEYWORDS,
- illegal: /[^\w\s\*&]/,
+ relevance: 0,
contains: [
+ hljs.C_LINE_COMMENT_MODE,
+ hljs.C_BLOCK_COMMENT_MODE,
+ STRINGS,
+ NUMBERS,
+ CPP_PRIMITIVE_TYPES,
+ // Count matching parentheses.
{
- begin: FUNCTION_TITLE, returnBegin: true,
- contains: [hljs.TITLE_MODE],
- relevance: 0
- },
- {
- className: 'params',
begin: /\(/, end: /\)/,
keywords: CPP_KEYWORDS,
relevance: 0,
contains: [
+ 'self',
hljs.C_LINE_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE,
STRINGS,
NUMBERS,
- CPP_PRIMITIVE_TYPES,
- // Count matching parentheses.
- {
- begin: /\(/, end: /\)/,
- keywords: CPP_KEYWORDS,
- relevance: 0,
- contains: [
- 'self',
- hljs.C_LINE_COMMENT_MODE,
- hljs.C_BLOCK_COMMENT_MODE,
- STRINGS,
- NUMBERS,
- CPP_PRIMITIVE_TYPES
- ]
- }
+ CPP_PRIMITIVE_TYPES
]
- },
- hljs.C_LINE_COMMENT_MODE,
- hljs.C_BLOCK_COMMENT_MODE,
- PREPROCESSOR
+ }
]
},
+ CPP_PRIMITIVE_TYPES,
+ hljs.C_LINE_COMMENT_MODE,
+ hljs.C_BLOCK_COMMENT_MODE,
+ PREPROCESSOR
+ ]
+ };
+
+ return {
+ aliases: ['c', 'cc', 'h', 'c++', 'h++', 'hpp', 'hh', 'hxx', 'cxx'],
+ keywords: CPP_KEYWORDS,
+ illegal: '',
+ contains: [].concat(
+ EXPRESSION_CONTEXT,
+ FUNCTION_DECLARATION,
+ EXPRESSION_CONTAINS,
+ [
+ PREPROCESSOR,
+ {
+ begin: '\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<', end: '>',
+ keywords: CPP_KEYWORDS,
+ contains: ['self', CPP_PRIMITIVE_TYPES]
+ },
+ {
+ begin: hljs.IDENT_RE + '::',
+ keywords: CPP_KEYWORDS
+ },
{
className: 'class',
beginKeywords: 'class struct', end: /[{;:]/,
diff --git a/test/markup/cpp/function-declarations.expect.txt b/test/markup/cpp/function-declarations.expect.txt
new file mode 100644
index 0000000000..5189214025
--- /dev/null
+++ b/test/markup/cpp/function-declarations.expect.txt
@@ -0,0 +1,16 @@
+decltype(auto) look_up_a_string_1() { return lookup1(); }
+void look_up_a_string_2() { return lookup2(); }
+friend void A::showB(B x) {}
+friend void showB(B x) {}
+friend void showB(B::SomeType x) {}
+inline int add(int a, int b) {}
+int8t Get_Tile_Value() {}
+
+int8_t Get_Tile_Value() {}
+
+B::type test() {};
+
+
+boost::optional<application> handle_key(application state, key_code key, coord size);
+
+test();
diff --git a/test/markup/cpp/function-declarations.txt b/test/markup/cpp/function-declarations.txt
new file mode 100644
index 0000000000..d196f5ca83
--- /dev/null
+++ b/test/markup/cpp/function-declarations.txt
@@ -0,0 +1,16 @@
+decltype(auto) look_up_a_string_1() { return lookup1(); }
+void look_up_a_string_2() { return lookup2(); }
+friend void A::showB(B x) {}
+friend void showB(B x) {}
+friend void showB(B::SomeType x) {}
+inline int add(int a, int b) {}
+int8t Get_Tile_Value() {}
+
+int8_t Get_Tile_Value() {}
+
+B::type test() {};
+
+// template
+boost::optional handle_key(application state, key_code key, coord size);
+
+test();