-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Backport 5.0] Highlighting: improve C++ (#49362)
Several small improvements to the C++ highlighting queries to improve readability. - Treat destructors as functions, same as constructors - Treat `unsigned` and `signed` as builtin types, same as primitive types like `bool` - Treat all-uppercase variables as identifiers instead of constants - Treat function declarations with field names as functions instead of fields - Treat `operator` in `operator==` as a keyword - Remove usages of `IdentifierOperator` because it's noisy, doesn't improve readability of the code and there were many false positives in the implementation - Include `~` in destructor names - Handle C++ attributes - Handle C++ literal suffixes - Adds new minimized test case for various language features ## Test plan See updated snapshot tests. <!-- All pull requests REQUIRE a test plan: https://docs.sourcegraph.com/dev/background-information/testing_principles --> <br> Backport 93a1101 from #49254 Co-authored-by: Ólafur Páll Geirsson <olafurpg@gmail.com>
- Loading branch information
1 parent
7419d69
commit f3ee4b8
Showing
6 changed files
with
1,363 additions
and
407 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
docker-images/syntax-highlighter/crates/sg-syntax/src/snapshots/files/cpp_example2.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// Stripped down from llvm/ADT/SmallSet.h (the code doesn't make sense) | ||
|
||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// \file | ||
/// This file defines the SmallSet class. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef BAD_SMALLSET_H | ||
#define BAD_SMALLSET_H | ||
|
||
#include "llvm/ADT/SmallPtrSet.h" | ||
#include <utility> | ||
|
||
namespace llvm { | ||
|
||
/// Doc comment | ||
template <typename T, unsigned N, const char *P, typename C = std::less<T>> | ||
class SmallSetIterator | ||
: public iterator_facade_base<SmallSetIterator<T, N>, | ||
std::forward_iterator_tag, T> { | ||
private: | ||
using SetIterTy = typename std::set<T, C>::const_iterator; | ||
using VecIterTy = typename SmallVector<T, N>::const_iterator; | ||
using SelfTy = SmallSetIterator<T, N, C>; | ||
|
||
// Non-doc comment | ||
union { | ||
SetIterTy SetIter; | ||
VecIterTy VecIter; | ||
}; | ||
|
||
bool isSmall; | ||
|
||
public: | ||
SmallSetIterator(SetIterTy SetIter) : SetIter(SetIter), isSmall(false) {} | ||
|
||
~SmallSetIterator() { | ||
if (isSmall) | ||
VecIter.~VecIterTy(); | ||
} | ||
|
||
SmallSetIterator(SmallSetIterator &&Other) : isSmall(Other.isSmall) { | ||
if (isSmall) | ||
VecIter = std::move(Other.VecIter); | ||
else | ||
// In-code comment | ||
new (&SetIter) SetIterTy(std::move(Other.SetIter)); | ||
} | ||
|
||
SmallSetIterator& operator=(const SmallSetIterator& Other) { | ||
return *this; | ||
} | ||
|
||
bool operator==(const SmallSetIterator &RHS) const { | ||
if (isSmall != RHS.isSmall) | ||
return false; | ||
if (isSmall) | ||
return VecIter == RHS.VecIter; | ||
} | ||
|
||
SmallSetIterator &operator++() { | ||
SetIter++; | ||
return *this; | ||
} | ||
|
||
const T &operator*() const { return isSmall ? *VecIter : *SetIter; } | ||
|
||
static_assert(N <= 32); // C++17 extension | ||
static_assert(N <= 32, "N should be small"); | ||
}; | ||
|
||
class SmallSet { | ||
SmallVector<T, N> Vector; | ||
std::set<T, C> Set; | ||
|
||
public: | ||
[[nodiscard]] bool empty() const { return Vector.empty(); } | ||
[[nodiscard("PURE FUN")]] int strategic_value(int x, int y) { return x^y; } | ||
|
||
std::pair<const_iterator, bool> insert(const T &V) { | ||
if (!isSmall()) { | ||
auto [I, Inserted] = Set.insert(V); | ||
return std::make_pair(const_iterator(I), Inserted); | ||
} | ||
} | ||
|
||
template <typename IterT> | ||
void insert(IterT I, IterT E) { | ||
for (; I != E; ++I) | ||
insert(*I); | ||
} | ||
|
||
const_iterator begin() const { | ||
if (isSmall()) | ||
return {Vector.begin()}; | ||
return {Set.begin()}; | ||
} | ||
}; | ||
|
||
#endif // BAD_SMALLSET_H |
200 changes: 200 additions & 0 deletions
200
docker-images/syntax-highlighter/crates/sg-syntax/src/snapshots/files/cpp_example3.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
#include <iostream> | ||
#include <map> | ||
#include <vector> | ||
|
||
void rangeBasedLoops() { | ||
std::vector<int> nums = {1, 2, 3, 4, 5}; | ||
|
||
// Iterate over vector using range-based for loop | ||
for (int num : nums) { | ||
std::cout << num << " "; | ||
} | ||
std::cout << std::endl; | ||
|
||
std::map<std::string, int> ages = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 35}}; | ||
|
||
// Iterate over map using range-based for loop | ||
for (const auto& [name, age] : ages) { | ||
std::cout << name << " is " << age << " years old." << std::endl; | ||
} | ||
} | ||
|
||
void closures() { | ||
int x = 5; | ||
|
||
// Define closure with capture | ||
auto add_x = [x](int y) { | ||
return x + y; | ||
}; | ||
|
||
// Call closure with different arguments | ||
std::cout << add_x(10) << std::endl; // prints 15 | ||
} | ||
|
||
// Define user-defined literal for string suffix "_s" | ||
std::string operator"" _s(const char* str, std::size_t len) { | ||
return std::string(str, len); | ||
} | ||
|
||
// Define user-defined literal for number suffix "_m" | ||
constexpr int operator"" _m(unsigned long long x) { | ||
return x * 1000; | ||
} | ||
|
||
void userDefinedLiterals() { | ||
// Use custom string literal suffix "_s" | ||
std::string s = "hello"_s; | ||
std::cout << s << std::endl; // prints "hello" | ||
|
||
int meters = 5_m; | ||
std::cout << meters << " meters" << std::endl; // prints "5000 meters" | ||
} | ||
|
||
#pragma once | ||
|
||
#include <iostream> | ||
|
||
#pragma warning(push) | ||
#pragma warning(disable: 4996) | ||
|
||
int pragmas() { | ||
#pragma message("This is a message from the preprocessor!") | ||
std::cout << "Hello, world!" << std::endl; | ||
|
||
return 0; | ||
} | ||
|
||
#pragma warning(pop) | ||
|
||
#define MESSAGE "Hello, world! This is a very long message that spans multiple lines. " \ | ||
"It is being continued using the line continuation character." | ||
|
||
#include <iostream> | ||
|
||
void preprocessorContinuations() { | ||
std::cout << MESSAGE << std::endl; | ||
} | ||
|
||
|
||
int andOrOperators() { | ||
int x = 5; | ||
int y = 10; | ||
bool b1 = x > 3 and y < 20; // b1 is true | ||
bool b2 = x < 3 or y > 20; // b2 is false | ||
bool b3 = x > 3 and y > 20; // b3 is false | ||
bool b4 = x < 3 or y < 20; // b4 is true | ||
} | ||
|
||
|
||
int multibyteCharacters() { | ||
std::string s1 = "Hello, world!"; // single-byte characters | ||
std::string s2 = "こんにちは世界!"; // multi-byte characters in UTF-8 encoding | ||
|
||
char c1 = 'A'; // single-byte character | ||
char c2 = u8'あ'; // multi-byte character encoded in UTF-8 | ||
|
||
|
||
std::cout << s1 << std::endl; | ||
std::cout << s2 << std::endl; | ||
|
||
return 0; | ||
} | ||
|
||
void literals() { | ||
auto intLit = 1234; | ||
auto floatLit = 1.23f; | ||
auto boolLit = true; | ||
char charLit = 'x'; | ||
auto stringLit = "Hello"; | ||
auto wideStringLit = L"World"; | ||
auto rawStringLit = R"(Hello | ||
World)"; | ||
auto nullptrLit = nullptr; | ||
} | ||
|
||
|
||
// Structs, enums, unions | ||
struct Point { | ||
int x; | ||
int y; | ||
Point() : x(0), y(0) { } // Default constructor | ||
Point(int x, int y) : x(x), y(y) { } // Initialization constructor | ||
}; | ||
enum Color { | ||
Red, | ||
Green, | ||
Blue | ||
}; | ||
union IntOrFloat { | ||
int i; | ||
float f; | ||
}; | ||
|
||
void structsEnumsUnions() { | ||
Point p {5, 10}; | ||
Color c = Blue; | ||
IntOrFloat iof; | ||
iof.i = 10; // Uses int member | ||
iof.f = 3.14f; // Now uses float member | ||
} | ||
|
||
// Templates | ||
template <typename T> | ||
void swap(T& a, T& b) { | ||
T temp = a; | ||
a = b; | ||
b = temp; | ||
} | ||
template <typename T, unsigned N> | ||
struct Array { | ||
T data[N]; | ||
}; | ||
|
||
void templates() { | ||
int x = 5, y = 10; | ||
swap(x, y); // x is now 10, y is now 5 | ||
double d1 = 1.2, d2 = 3.4; | ||
swap(d1, d2); // d1 is now 3.4, d2 is now 1.2 | ||
Array<int, 10> ints; // Holds 10 ints | ||
Array<char, 100> chars; // Holds 100 chars | ||
} | ||
|
||
// Classes | ||
class Person { | ||
public: | ||
Person(std::string name, int age); // Constructor | ||
~Person(); // Destructor | ||
std::string getName(); // Accessor method | ||
// Virtual method | ||
virtual void greeting(); | ||
// Overloaded operator | ||
friend std::ostream& operator<<(std::ostream& os, const Person& p); | ||
private: | ||
std::string name; | ||
int age; | ||
}; | ||
class Employee : public Person { // Inherits from Person | ||
public: | ||
Employee(std::string name, int age, std::string company); | ||
// Overridden virtual method | ||
void greeting() override; | ||
}; | ||
|
||
// Attributes | ||
[[my_attribute]] | ||
struct my_attribute { | ||
int value; | ||
}; | ||
|
||
namespace std { | ||
template <> | ||
struct has_attribute<my_attribute> : true_type { }; | ||
} | ||
|
||
void attributes() { | ||
[[my_attribute(5)]] int data; | ||
if (has_attribute<my_attribute>(myData)) { | ||
// data has the my_attribute attribute | ||
} | ||
} | ||
} |
Oops, something went wrong.