Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 60x 167x 167x 17x 10x 7x 50x 17x 17x 34x 4x 30x 13x 13x 6x 13x 82x 71x 4x 67x 64x 60x 50x | /**
* Issue #208: Detect if header content contains C++ syntax requiring C++14 parser
*
* This heuristic determines whether to parse a .h file with the C or C++ parser.
* Previously, the pipeline would parse ALL .h files with BOTH parsers and merge,
* which was wasteful and led to issues with C++-specific features like typed enums.
*
* C++ indicators:
* - Typed enums: enum Name : type { ... }
* - Class/struct inheritance: class Foo : public Bar
* - Namespaces: namespace Foo { ... }
* - Templates: template<...>
* - Access specifiers: public:, private:, protected:
*/
/**
* True when the source contains an access-specifier label, as
* /^\s*(public|private|protected)\s*:/m did.
*
* Scanned rather than matched: under /m the leading \s* can span newlines, so
* the engine retries that run from every line start (S8786).
*
* Both whitespace runs may cross lines, matching the original: only whitespace
* may precede the keyword on its line, and the colon may sit on a later line.
*/
function hasAccessSpecifierLabel(content: string): boolean {
for (const keyword of ["public", "private", "protected"]) {
let from = content.indexOf(keyword);
while (from !== -1) {
if (isAccessSpecifierAt(content, from, keyword.length)) {
return true;
}
from = content.indexOf(keyword, from + 1);
}
}
return false;
}
/** Only whitespace before it on its line, and a colon after any whitespace. */
function isAccessSpecifierAt(
content: string,
start: number,
length: number,
): boolean {
let before = start - 1;
while (before >= 0 && content[before] !== "\n") {
if (!/\s/.test(content[before])) {
return false;
}
before -= 1;
}
let after = start + length;
while (after < content.length && /\s/.test(content[after])) {
after += 1;
}
return content[after] === ":";
}
/**
* Detect if header content contains C++ syntax requiring C++14 parser
* @param content Raw header file content
* @returns true if C++ parser should be used, false for C parser
*/
function detectCppSyntax(content: string): boolean {
// Typed enums: enum Name : type { (C++14 feature, key for Issue #208)
if (/enum\s+\w+\s*:\s*\w+\s*\{/.test(content)) return true;
// Class/struct with inheritance: class Foo : public/private/protected Bar
if (/\b(class|struct)\s+\w+\s*:\s*(public|private|protected)/.test(content))
return true;
// namespace keyword: namespace Foo {
if (/\bnamespace\s+\w+/.test(content)) return true;
// template declarations: template<...>
if (/\btemplate\s*</.test(content)) return true;
// Access specifiers at line start (class members)
if (hasAccessSpecifierLabel(content)) return true;
// Default to C parser for pure C headers
return false;
}
export default detectCppSyntax;
|