Add comprehensive coding guidelines for GitHub Copilot to improve quality and consistency of AI-generated code. Instructions cover C++ and Python development with language-specific best practices, build system usage, and testing workflows. Following GitHub Copilot's standard layout with general instructions in .github/copilot-instructions.md and language-specific files in .github/instructions/ directory using *.instructions.md naming. No backport: This change is only for developers in master, so it doesn't need to be backported. Closes scylladb/scylladb#25374
5.0 KiB
5.0 KiB
applyTo
| applyTo |
|---|
| **/*.{cc,hh} |
C++ Guidelines
Important: Always match the style and conventions of existing code in the file and directory.
Memory Management
- Prefer stack allocation whenever possible
- Use
std::unique_ptrby default for dynamic allocations new/deleteare forbidden (use RAII)- Use
seastar::lw_shared_ptrorseastar::shared_ptrfor shared ownership within same shard - Use
seastar::foreign_ptrfor cross-shard sharing - Avoid
std::shared_ptrexcept when interfacing with external C++ APIs - Avoid raw pointers except for non-owning references or C API interop
Seastar Asynchronous Programming
- Use
seastar::future<T>for all async operations - Prefer coroutines (
co_await,co_return) over.then()chains for readability - Coroutines are preferred over
seastar::do_with()for managing temporary state - In hot paths where futures are ready, continuations may be more efficient than coroutines
- Chain futures with
.then(), don't block with.get()(unless inseastar::threadcontext) - All I/O must be asynchronous (no blocking calls)
- Use
seastar::gatefor shutdown coordination - Use
seastar::semaphorefor resource limiting (notstd::mutex) - Break long loops with
maybe_yield()to avoid reactor stalls
Coroutines
seastar::future<T> func() {
auto result = co_await async_operation();
co_return result;
}
Error Handling
- Throw exceptions for errors (futures propagate them automatically)
- In data path: avoid exceptions, use
std::expected(orboost::outcome) instead - Use standard exceptions (
std::runtime_error,std::invalid_argument) - Database-specific: throw appropriate schema/query exceptions
Performance
- Pass large objects by
const&or&&(move semantics) - Use
std::string_viewfor non-owning string references - Avoid copies: prefer move semantics
- Use
utils::chunked_vectorinstead ofstd::vectorfor large allocations (>128KB) - Minimize dynamic allocations in hot paths
Database-Specific Types
- Use
schema_ptrfor schema references - Use
mutationandmutation_partitionfor data modifications - Use
partition_keyandclustering_keyfor keys - Use
api::timestamp_typefor database timestamps - Use
gc_clockfor garbage collection timing
Style
- C++23 standard (prefer modern features, especially coroutines)
- Use
autowhen type is obvious from RHS - Avoid
autowhen it obscures the type - Use range-based for loops:
for (const auto& item : container) - Use standard algorithms when they clearly simplify code (e.g., replacing 10-line loops)
- Avoid chaining multiple algorithms if a straightforward loop is clearer
- Mark functions and variables
constwhenever possible - Use scoped enums:
enum class(not unscopedenum)
Headers
- Use
#pragma once - Include order: own header, C++ std, Seastar, Boost, project headers
- Forward declare when possible
- Never
using namespacein headers (exception:using namespace seastaris globally available viaseastarx.hh)
Documentation
- Public APIs require clear documentation
- Implementation details should be self-evident from code
- Use
///or Doxygen/** */for public documentation,//for implementation notes - follow the existing style
Naming
snake_casefor most identifiers (classes, functions, variables, namespaces)- Template parameters:
CamelCase(e.g.,template<typename ValueType>) - Member variables: prefix with
_(e.g.,int _count;) - Structs (value-only): no
_prefix on members - Constants and
constexpr:snake_case(e.g.,static constexpr int max_size = 100;) - Files:
.hhfor headers,.ccfor source
Formatting
- 4 spaces indentation, never tabs
- Opening braces on same line as control structure (except namespaces)
- Space after keywords:
if (,while (,return - Whitespace around operators matches precedence:
*a + *bnot* a+* b - Line length: keep reasonable (<160 chars), use continuation lines with double indent if needed
- Brace all nested scopes, even single statements
- Minimal patches: only format code you modify, never reformat entire files
Logging
- Use structured logging with appropriate levels: DEBUG, INFO, WARN, ERROR
- Include context in log messages (e.g., request IDs)
- Never log sensitive data (credentials, PII)
Forbidden
malloc/freeprintffamily (use logging or fmt)- Raw pointers for ownership
using namespacein headers- Blocking operations:
std::sleep,std::read,std::mutex(use Seastar equivalents) std::atomic(reserved for very special circumstances only)- Macros (use
inline,constexpr, or templates instead)
Testing
When modifying existing code, follow TDD: create/update test first, then implement.
- Examine existing tests for style and structure
- Use Boost.Test framework
- Use
SEASTAR_THREAD_TEST_CASEfor Seastar asynchronous tests - Aim for high code coverage, especially for new features and bug fixes
- Maintain bisectability: all tests must pass in every commit. Mark failing tests with
BOOST_FAIL()or similar, then fix in subsequent commit