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

Added list of false positiitives #3999

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ CAVEATS / POTENTIALLY BREAKING CHANGES

Core Grammars:

- fix(cpp) Keywords followed by parens are treated as built_in [Md Saad Akhtar][]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add your author link below as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping.

- enh(typescript) add support for `satisfies` operator [Kisaragi Hiu][]
- enc(c) added more C23 keywords [Melkor-1][]
- enh(json) added jsonc as an alias [BackupMiles][]
Expand Down Expand Up @@ -186,7 +187,6 @@ New Grammars:
- added 3rd party Ballerina grammar to SUPPORTED_LANGUAGES [Yasith Deelaka][]

Core Grammars:

- fix(cpp) fixed highlighter break state [Md Saad Akhtar][]
- fix(rust) added negative-lookahead for callable keywords `if` `while` `for` [Omar Hussein][]
- enh(armasm) added `x0-x30` and `w0-w30` ARMv8 registers [Nicholas Thompson][]
Expand Down
16 changes: 10 additions & 6 deletions src/languages/cpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,14 @@ export default function(hljs) {
_type_hints: TYPE_HINTS
};

const allKeywords = [
...CPP_KEYWORDS.type,
...CPP_KEYWORDS.keyword,
...CPP_KEYWORDS.literal,
...CPP_KEYWORDS.built_in,
...CPP_KEYWORDS._type_hints
];

const FUNCTION_DISPATCH = {
className: 'function.dispatch',
relevance: 0,
Expand All @@ -423,15 +431,11 @@ export default function(hljs) {
_hint: FUNCTION_HINTS },
begin: regex.concat(
/\b/,
/(?!decltype)/,
/(?!if)/,
/(?!for)/,
/(?!switch)/,
/(?!while)/,
// adds all keywords dynamically
...allKeywords.map(keyword => new RegExp(`(?!${keyword})`)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually don't we only care about keywords here that can potentially have a ( following them? That's not ALL keywords, is it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can ignore this for now since I already said this was ready but need your author link...

hljs.IDENT_RE,
regex.lookahead(/(<[^<>]+>|)\s*\(/))
};

const EXPRESSION_CONTAINS = [
FUNCTION_DISPATCH,
PREPROCESSOR,
Expand Down
93 changes: 93 additions & 0 deletions test/markup/cpp/keywords-with-parentheses.expect.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<span class="hljs-keyword">alignas</span>(<span class="hljs-number">16</span>) <span class="hljs-type">char</span> aligned_buffer[<span class="hljs-number">1024</span>];
<span class="hljs-keyword">alignof</span>(<span class="hljs-keyword">decltype</span>(aligned_buffer))
<span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;movl $1, %eax&quot;</span>);
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">throw</span> std::<span class="hljs-built_in">runtime_error</span>(<span class="hljs-string">&quot;An exception occurred&quot;</span>);
} <span class="hljs-keyword">catch</span> (<span class="hljs-type">const</span> std::exception&amp; e) {
std::cout &lt;&lt; <span class="hljs-string">&quot;Caught exception: &quot;</span> &lt;&lt; e.<span class="hljs-built_in">what</span>() &lt;&lt; std::endl;
}
<span class="hljs-type">const</span> <span class="hljs-type">int</span>* p = <span class="hljs-literal">nullptr</span>;
<span class="hljs-type">int</span>* mutable_p = <span class="hljs-keyword">const_cast</span>&lt;<span class="hljs-type">int</span>*&gt;(p);
<span class="hljs-type">int</span> x = <span class="hljs-number">5</span>;
<span class="hljs-keyword">decltype</span>(x) y = <span class="hljs-number">10</span>;
Animal* animal = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Dog</span>();
<span class="hljs-keyword">if</span> (Dog* dog = <span class="hljs-keyword">dynamic_cast</span>&lt;Dog*&gt;(animal)) {
std::cout &lt;&lt; <span class="hljs-string">&quot;Dynamic cast successful&quot;</span> &lt;&lt; std::endl;
} <span class="hljs-keyword">else</span> {
std::cout &lt;&lt; <span class="hljs-string">&quot;Dynamic cast failed&quot;</span> &lt;&lt; std::endl;
}
<span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-type">int</span> a, <span class="hljs-type">int</span> b)</span> <span class="hljs-keyword">noexcept</span> </span>{
<span class="hljs-keyword">return</span> a + b;
}
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">noexcept</span>(<span class="hljs-built_in">add</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>))) {
<span class="hljs-comment">// The add function will not throw an exception.</span>
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// The add function may throw an exception.</span>
}
<span class="hljs-type">int</span> value = <span class="hljs-number">10</span>;
<span class="hljs-type">double</span>* ptr = <span class="hljs-keyword">reinterpret_cast</span>&lt;<span class="hljs-type">double</span>*&gt;(&amp;value);
std::cout &lt;&lt; <span class="hljs-string">&quot;Size of int: &quot;</span> &lt;&lt; <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>) &lt;&lt; <span class="hljs-string">&quot; bytes&quot;</span> &lt;&lt; std::endl;
<span class="hljs-keyword">static_assert</span>(<span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>) == <span class="hljs-number">4</span>, <span class="hljs-string">&quot;int must be 4 bytes&quot;</span>);
<span class="hljs-type">float</span> z = <span class="hljs-keyword">static_cast</span>&lt;<span class="hljs-type">float</span>&gt;(<span class="hljs-number">10</span>);
<span class="hljs-type">int</span> choice = <span class="hljs-number">2</span>;
<span class="hljs-keyword">switch</span>(choice) {
<span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
std::cout &lt;&lt; <span class="hljs-string">&quot;Choice is 1&quot;</span> &lt;&lt; std::endl;
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
std::cout &lt;&lt; <span class="hljs-string">&quot;Choice is 2&quot;</span> &lt;&lt; std::endl;
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">default</span>:
std::cout &lt;&lt; <span class="hljs-string">&quot;Choice is not 1 or 2&quot;</span> &lt;&lt; std::endl;
}
std::cout &lt;&lt; <span class="hljs-string">&quot;Type of x: &quot;</span> &lt;&lt; <span class="hljs-keyword">typeid</span>(x).<span class="hljs-built_in">name</span>() &lt;&lt; std::endl;
<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;
<span class="hljs-keyword">while</span>(i &lt; <span class="hljs-number">5</span>) {
std::cout &lt;&lt; <span class="hljs-string">&quot;Iteration &quot;</span> &lt;&lt; i &lt;&lt; std::endl;
i++;
}
<span class="hljs-comment">// requires</span>
<span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">class</span> <span class="hljs-title class_">T</span>&gt;
<span class="hljs-keyword">concept</span> dereferenceable =
<span class="hljs-keyword">requires</span> { <span class="hljs-keyword">typename</span> <span class="hljs-type">iter_value_t</span>&lt;I&gt;; } <span class="hljs-function"><span class="hljs-keyword">and</span>
<span class="hljs-title">requires</span><span class="hljs-params">(I i)</span> </span>{
*i;
};

<span class="hljs-comment">// explicit</span>
<span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">class</span> <span class="hljs-title class_">T</span>&gt;
<span class="hljs-keyword">struct</span> <span class="hljs-title class_">S</span> {
<span class="hljs-keyword">explicit</span>(weakly_incrementable&lt;T&gt;) <span class="hljs-built_in">S</span>();
};

<span class="hljs-comment">// auto, operators</span>
<span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
<span class="hljs-keyword">auto</span> x = <span class="hljs-keyword">auto</span>(<span class="hljs-number">0</span>);
x bitand_eq x; <span class="hljs-comment">// needs to be added too</span>
<span class="hljs-function">x <span class="hljs-title">bitand_eq</span> <span class="hljs-params">(x)</span></span>;
x bitor_eq x; <span class="hljs-comment">// needs to be added too</span>
<span class="hljs-function">x <span class="hljs-title">bitor_eq</span> <span class="hljs-params">(x)</span></span>;
x <span class="hljs-keyword">xor</span> x;
<span class="hljs-function">x <span class="hljs-title">xor</span> <span class="hljs-params">(x)</span></span>;
x <span class="hljs-keyword">and</span> x;
<span class="hljs-function">x <span class="hljs-title">and</span> <span class="hljs-params">(x)</span></span>;
x <span class="hljs-keyword">or</span> x;
<span class="hljs-function">x <span class="hljs-title">or</span> <span class="hljs-params">(x)</span></span>;
x <span class="hljs-keyword">bitand</span> x;
<span class="hljs-function">x <span class="hljs-title">bitand</span> <span class="hljs-params">(x)</span></span>;
x <span class="hljs-keyword">bitor</span> x;
<span class="hljs-function">x <span class="hljs-title">bitor</span> <span class="hljs-params">(x)</span></span>;
x <span class="hljs-keyword">not_eq</span> x;
<span class="hljs-function">x <span class="hljs-title">not_eq</span> <span class="hljs-params">(x)</span></span>;
<span class="hljs-keyword">not</span> x;
<span class="hljs-keyword">not</span> (x);
<span class="hljs-keyword">compl</span> x;
<span class="hljs-keyword">compl</span> (x);
<span class="hljs-keyword">co_await</span> x;
<span class="hljs-keyword">co_await</span> (x);
<span class="hljs-keyword">co_return</span> x;
<span class="hljs-keyword">co_return</span> (x);
<span class="hljs-keyword">co_yield</span> x;
<span class="hljs-keyword">co_yield</span> (x);
}
93 changes: 93 additions & 0 deletions test/markup/cpp/keywords-with-parentheses.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
alignas(16) char aligned_buffer[1024];
alignof(decltype(aligned_buffer))
asm("movl $1, %eax");
try {
throw std::runtime_error("An exception occurred");
} catch (const std::exception& e) {
std::cout << "Caught exception: " << e.what() << std::endl;
}
const int* p = nullptr;
int* mutable_p = const_cast<int*>(p);
int x = 5;
decltype(x) y = 10;
Animal* animal = new Dog();
if (Dog* dog = dynamic_cast<Dog*>(animal)) {
std::cout << "Dynamic cast successful" << std::endl;
} else {
std::cout << "Dynamic cast failed" << std::endl;
}
int add(int a, int b) noexcept {
return a + b;
}
if (noexcept(add(1, 2))) {
// The add function will not throw an exception.
} else {
// The add function may throw an exception.
}
int value = 10;
double* ptr = reinterpret_cast<double*>(&value);
std::cout << "Size of int: " << sizeof(int) << " bytes" << std::endl;
static_assert(sizeof(int) == 4, "int must be 4 bytes");
float z = static_cast<float>(10);
int choice = 2;
switch(choice) {
case 1:
std::cout << "Choice is 1" << std::endl;
break;
case 2:
std::cout << "Choice is 2" << std::endl;
break;
default:
std::cout << "Choice is not 1 or 2" << std::endl;
}
std::cout << "Type of x: " << typeid(x).name() << std::endl;
int i = 0;
while(i < 5) {
std::cout << "Iteration " << i << std::endl;
i++;
}
// requires
template<class T>
concept dereferenceable =
requires { typename iter_value_t<I>; } and
requires(I i) {
*i;
};

// explicit
template<class T>
struct S {
explicit(weakly_incrementable<T>) S();
};

// auto, operators
int main()
{
auto x = auto(0);
x bitand_eq x; // needs to be added too
x bitand_eq (x);
x bitor_eq x; // needs to be added too
x bitor_eq (x);
x xor x;
x xor (x);
x and x;
x and (x);
x or x;
x or (x);
x bitand x;
x bitand (x);
x bitor x;
x bitor (x);
x not_eq x;
x not_eq (x);
not x;
not (x);
compl x;
compl (x);
co_await x;
co_await (x);
co_return x;
co_return (x);
co_yield x;
co_yield (x);
}
2 changes: 1 addition & 1 deletion test/markup/cpp/template-complexity.expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">class</span> <span class="hljs-title class_">T</span>, <span class="hljs-keyword">class</span> = std::<span class="hljs-type">enable_if_t</span>&lt;!impl::is_streamable_v&lt;<span class="hljs-type">const</span> T &amp;&gt; &amp;&amp; std::is_convertible_v&lt;<span class="hljs-type">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-type">const</span> T &amp;thing)
{
<span class="hljs-keyword">return</span> stream &lt;&lt; <span class="hljs-built_in">static_cast</span>&lt;std::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-keyword">enum struct</span> <span class="hljs-title class_">DataHolder</span> { };
Expand Down