Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enh(cpp) Highlight all function dispatches #3005

Merged
merged 8 commits into from
Mar 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ New Languages:

Language grammar improvements:

- enh(cpp) Highlight all function dispatches (#3005) [Josh Goebel][]
- enh(python) support type hints and better type support (#2972) [Josh Goebel][]
- enh(gml) Add additional GML 2.3 keywords (#2984) [xDGameStudios][]
- fix(cpp) constructor support for initializers (#3001) [Josh Goebel][]
Expand Down
6 changes: 4 additions & 2 deletions docs/language-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,14 @@ object, each property of which defines its own group of keywords:
{
keywords: {
keyword: 'else for if while',
literal: ['false','true','null']
literal: ['false','true','null'],
_relevance_only: 'one two three four'
}
}

The group name becomes the class name in the generated markup, enabling different
theming for different kinds of keywords.
theming for different kinds of keywords. Any property starting with a ``_`` will
only use those keywords to increase relevance, they will not be highlighted.

To detect keywords, highlight.js breaks the processed chunk of code into separate
words — a process called lexing. By default, "words" are matched with the regexp
Expand Down
10 changes: 8 additions & 2 deletions src/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,14 @@ const HLJS = function(hljs) {
buf = "";

relevance += keywordRelevance;
const cssClass = language.classNameAliases[kind] || kind;
emitter.addKeyword(match[0], cssClass);
if (kind.startsWith("_")) {
// _ implied for relevance only, do not highlight
// by applying a class name
buf += match[0];
} else {
const cssClass = language.classNameAliases[kind] || kind;
emitter.addKeyword(match[0], cssClass);
}
} else {
buf += match[0];
}
Expand Down
6 changes: 4 additions & 2 deletions src/languages/arduino.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export default function(hljs) {
keyword:
'boolean byte word String',
built_in:
'setup loop ' +
'KeyboardController MouseController SoftwareSerial ' +
'EthernetServer EthernetClient LiquidCrystal ' +
'RobotControl GSMVoiceCall EthernetUDP EsploraTFT ' +
Expand All @@ -24,7 +23,9 @@ export default function(hljs) {
'WiFiUDP GSM_SMS Mailbox USBHost Firmata PImage ' +
'Client Server GSMPIN FileIO Bridge Serial ' +
'EEPROM Stream Mouse Audio Servo File Task ' +
'GPRS WiFi Wire TFT GSM SPI SD ' +
'GPRS WiFi Wire TFT GSM SPI SD ',
_:
'setup loop ' +
'runShellCommandAsynchronously analogWriteResolution ' +
'retrieveCallingNumber printFirmwareVersion ' +
'analogReadResolution sendDigitalPortPair ' +
Expand Down Expand Up @@ -102,6 +103,7 @@ export default function(hljs) {
kws.keyword += ' ' + ARDUINO_KW.keyword;
kws.literal += ' ' + ARDUINO_KW.literal;
kws.built_in += ' ' + ARDUINO_KW.built_in;
kws._ += ' ' + ARDUINO_KW._;

ARDUINO.name = 'Arduino';
ARDUINO.aliases = ['ino'];
Expand Down
147 changes: 138 additions & 9 deletions src/languages/cpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,122 @@ export default function(hljs) {

const FUNCTION_TITLE = regex.optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';

const COMMON_CPP_HINTS = [
'asin',
'atan2',
'atan',
'calloc',
'ceil',
'cosh',
'cos',
'exit',
'exp',
'fabs',
'floor',
'fmod',
'fprintf',
'fputs',
'free',
'frexp',
'auto_ptr',
'deque',
'list',
'queue',
'stack',
'vector',
'map',
'set',
'pair',
'bitset',
'multiset',
'multimap',
'unordered_set',
'fscanf',
'future',
'isalnum',
'isalpha',
'iscntrl',
'isdigit',
'isgraph',
'islower',
'isprint',
'ispunct',
'isspace',
'isupper',
'isxdigit',
'tolower',
'toupper',
'labs',
'ldexp',
'log10',
'log',
'malloc',
'realloc',
'memchr',
'memcmp',
'memcpy',
'memset',
'modf',
'pow',
'printf',
'putchar',
'puts',
'scanf',
'sinh',
'sin',
'snprintf',
'sprintf',
'sqrt',
'sscanf',
'strcat',
'strchr',
'strcmp',
'strcpy',
'strcspn',
'strlen',
'strncat',
'strncmp',
'strncpy',
'strpbrk',
'strrchr',
'strspn',
'strstr',
'tanh',
'tan',
'unordered_map',
'unordered_multiset',
'unordered_multimap',
'priority_queue',
'make_pair',
'array',
'shared_ptr',
'abort',
'terminate',
'abs',
'acos',
'vfprintf',
'vprintf',
'vsprintf',
'endl',
'initializer_list',
'unique_ptr',
'complex',
'imaginary',
'std',
'string',
'wstring',
'cin',
'cout',
'cerr',
'clog',
'stdin',
'stdout',
'stderr',
'stringstream',
'istringstream',
'ostringstream'
];

const CPP_KEYWORDS = {
keyword: 'int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof ' +
'dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace ' +
Expand All @@ -120,19 +236,27 @@ export default function(hljs) {
'atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong ' +
'atomic_ullong new throw return ' +
'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq',
built_in: 'std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream ' +
'auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set ' +
'unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos ' +
'asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp ' +
'fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper ' +
'isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow ' +
'printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp ' +
'strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan ' +
'vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary',
built_in: '_Bool _Complex _Imaginary',
_relevance_hints: COMMON_CPP_HINTS,
joshgoebel marked this conversation as resolved.
Show resolved Hide resolved
literal: 'true false nullptr NULL'
};

const FUNCTION_DISPATCH = {
className: "function.dispatch",
relevance: 0,
keywords: CPP_KEYWORDS,
begin: regex.concat(
/\b/,
/(?!decltype)/,
/(?!if)/,
/(?!for)/,
/(?!while)/,
hljs.IDENT_RE,
regex.lookahead(/\s*\(/))
};

const EXPRESSION_CONTAINS = [
FUNCTION_DISPATCH,
PREPROCESSOR,
CPP_PRIMITIVE_TYPES,
C_LINE_COMMENT_MODE,
Expand All @@ -141,6 +265,7 @@ export default function(hljs) {
STRINGS
];


const EXPRESSION_CONTEXT = {
// This mode covers expression context where we can't expect a function
// definition and shouldn't highlight anything that looks like one:
Expand Down Expand Up @@ -256,9 +381,13 @@ export default function(hljs) {
],
keywords: CPP_KEYWORDS,
illegal: '</',
classNameAliases: {
"function.dispatch": "built_in"
},
contains: [].concat(
EXPRESSION_CONTEXT,
FUNCTION_DECLARATION,
FUNCTION_DISPATCH,
EXPRESSION_CONTAINS,
[
PREPROCESSOR,
Expand Down
7 changes: 4 additions & 3 deletions test/markup/cpp/function-declarations.expect.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<span class="hljs-function"><span class="hljs-keyword">decltype</span>(<span class="hljs-keyword">auto</span>) <span class="hljs-title">look_up_a_string_1</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> lookup1(); }
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">look_up_a_string_2</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> lookup2(); }
<span class="hljs-function"><span class="hljs-keyword">decltype</span>(<span class="hljs-keyword">auto</span>) <span class="hljs-title">look_up_a_string_1</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-built_in">lookup1</span>(); }
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">look_up_a_string_2</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-built_in">lookup2</span>(); }
<span class="hljs-function"><span class="hljs-keyword">friend</span> <span class="hljs-keyword">void</span> <span class="hljs-title">A::showB</span><span class="hljs-params">(B x)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">friend</span> <span class="hljs-keyword">void</span> <span class="hljs-title">showB</span><span class="hljs-params">(B x)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">friend</span> <span class="hljs-keyword">void</span> <span class="hljs-title">showB</span><span class="hljs-params">(B::SomeType x)</span> </span>{}
Expand All @@ -17,7 +17,8 @@
<span class="hljs-function"><span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">typename</span> T...&gt;
<span class="hljs-keyword">void</span> <span class="hljs-title">foo</span><span class="hljs-params">(T... args)</span> </span>{}

test();
<span class="hljs-built_in">test</span>();

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">A</span><span class="hljs-params">()</span>: a(<span class="hljs-number">10</span>) {</span>}
<span class="hljs-function"><span class="hljs-keyword">explicit</span> <span class="hljs-title">A</span><span class="hljs-params">()</span>: a(<span class="hljs-number">10</span>) {</span>}

10 changes: 5 additions & 5 deletions test/markup/cpp/function-title.expect.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
A a = <span class="hljs-keyword">new</span> A();
<span class="hljs-keyword">int</span> b = b * sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>);
<span class="hljs-keyword">if</span> (a-&gt;check1())
A a = <span class="hljs-keyword">new</span> <span class="hljs-built_in">A</span>();
<span class="hljs-keyword">int</span> b = b * <span class="hljs-built_in">sum</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>);
<span class="hljs-keyword">if</span> (a-&gt;<span class="hljs-built_in">check1</span>())
<span class="hljs-keyword">return</span> <span class="hljs-number">3</span>;
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (a-&gt;check2())
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (a-&gt;<span class="hljs-built_in">check2</span>())
<span class="hljs-keyword">return</span> <span class="hljs-number">4</span>;
<span class="hljs-keyword">return</span> a-&gt;result();
<span class="hljs-keyword">return</span> a-&gt;<span class="hljs-built_in">result</span>();
}
4 changes: 2 additions & 2 deletions test/markup/cpp/preprocessor.expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@

<span class="hljs-keyword">if</span> (p) {
<span class="hljs-meta">#<span class="hljs-meta-keyword">ifdef</span> DEBUG</span>
onething();
<span class="hljs-built_in">onething</span>();
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (errno) {
<span class="hljs-meta">#<span class="hljs-meta-keyword">ifdef</span> DEBUG</span>
anotherthing();
<span class="hljs-built_in">anotherthing</span>();
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
}

Expand Down
8 changes: 4 additions & 4 deletions test/markup/cpp/template_complexity.expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

<span class="hljs-keyword">namespace</span> impl {
<span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">typename</span> T&gt;
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">is_streamable</span>&lt;</span>T, <span class="hljs-built_in">std</span>::<span class="hljs-keyword">void_t</span>&lt;<span class="hljs-keyword">decltype</span>(<span class="hljs-built_in">std</span>::declval&lt;<span class="hljs-built_in">std</span>::wostream &amp;&gt;() &lt;&lt; <span class="hljs-built_in">std</span>::declval&lt;T&gt;())&gt;&gt; : <span class="hljs-built_in">std</span>::true_type { };
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">is_streamable</span>&lt;</span>T, std::<span class="hljs-keyword">void_t</span>&lt;<span class="hljs-keyword">decltype</span>(std::declval&lt;std::wostream &amp;&gt;() &lt;&lt; std::declval&lt;T&gt;())&gt;&gt; : std::true_type { };
}

<span class="hljs-comment">// Disable overload for already valid operands.</span>
<span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">T</span>, <span class="hljs-keyword">class</span> =</span> <span class="hljs-built_in">std</span>::<span class="hljs-keyword">enable_if_t</span>&lt;!impl::is_streamable_v&lt;<span class="hljs-keyword">const</span> T &amp;&gt; &amp;&amp; <span class="hljs-built_in">std</span>::is_convertible_v&lt;<span class="hljs-keyword">const</span> T &amp;, <span class="hljs-built_in">std</span>::wstring_view&gt;&gt;&gt;
<span class="hljs-built_in">std</span>::wostream &amp;<span class="hljs-keyword">operator</span> &lt;&lt;(<span class="hljs-built_in">std</span>::wostream &amp;stream, <span class="hljs-keyword">const</span> T &amp;thing)
<span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">T</span>, <span class="hljs-keyword">class</span> =</span> std::<span class="hljs-keyword">enable_if_t</span>&lt;!impl::is_streamable_v&lt;<span class="hljs-keyword">const</span> T &amp;&gt; &amp;&amp; std::is_convertible_v&lt;<span class="hljs-keyword">const</span> T &amp;, std::wstring_view&gt;&gt;&gt;
std::wostream &amp;<span class="hljs-keyword">operator</span> &lt;&lt;(std::wostream &amp;stream, <span class="hljs-keyword">const</span> T &amp;thing)
{
<span class="hljs-keyword">return</span> stream &lt;&lt; <span class="hljs-keyword">static_cast</span>&lt;<span class="hljs-built_in">std</span>::wstring_view&gt;(thing);
<span class="hljs-keyword">return</span> stream &lt;&lt; <span class="hljs-keyword">static_cast</span>&lt;std::wstring_view&gt;(thing);
}

<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-keyword">struct</span> <span class="hljs-title">DataHolder</span> {</span> };
Expand Down