Nvim の :help
ページは、生成されたもので、ソースをtree-sitter-vimdocパーサーを使って生成しています。
#pragma once
で始める必要があります。#pragma once
fileio.h
と fileio_defs.h
です。この区別は、変更時の再コンパイルを最小限に抑えるために行われます。これは、関数の追加や関数のシグネチャの変更が型の変更よりも頻繁に発生するためです。目標は以下を達成することです。extern
変数 (EXTERN
マクロを含む)#define
FUNC_ATTR_ALWAYS_INLINE
属性を持つ static inline 関数int i;
i = f(); // ❌: initialization separate from declaration.
int j = g(); // ✅: declaration has initialization.
int i;
int j; // ✅
int i, j; // ✅: multiple declarations, no initialization.
int i = 0;
int j = 0; // ✅: one initialization per line.
int i = 0, j; // ❌: multiple declarations with initialization.
int i = 0, j = 0; // ❌: multiple declarations with initialization.
clint.py
を使用します。src/clint.py
は、ソースファイルを読み取り、スタイルエラーを特定する Python スクリプトです。完璧ではなく、誤検出と誤陰性の両方がありますが、それでも貴重なツールです。誤検出は、行末に // NOLINT
を付けることで無視できます。alloca()
は許可されていません。i++
)を使用します。for (int i = 0; i < 3; i++) { }
int j = ++i; // ✅: ++i is used as an expression.
for (int i = 0; i < 3; ++i) { }
++i; // ❌: ++i is used as a statement.
const
ポインターを使用します。非ポインターパラメーター定義で const
を使用することは避けてください。const int *foo
の代わりに int const *foo
の形式を好む人もいます。これは、const
が記述しているオブジェクトの後に常に続くというルールを維持しているため、より読みやすいと主張します。ただし、この一貫性の議論は、ほとんどの const
式が1つの const
しか持たず、基になる値に適用されるため、深くネストされたポインター式が少ないコードベースには当てはまりません。このような場合、維持すべき一貫性はありません。最初に const
を配置することは、英語の「形容詞」(const
)を「名詞」(int
)の前に置くことに従うため、より読みやすいと言えます。const
を配置することを推奨しますが、必須ではありません。ただし、周りのコードと一貫性を持たせてください!void foo(const char *p, int i);
}
int foo(const int a, const bool b) {
}
int foo(int *const p) {
}
char
、int
、uint8_t
、int8_t
、uint16_t
、int16_t
、uint32_t
、int32_t
、uint64_t
、int64_t
、uintmax_t
、intmax_t
、size_t
、ssize_t
、uintptr_t
、intptr_t
、および ptrdiff_t
のみを使用します。int
のみを使用します。char
の符号付きは実装定義であることに注意してください。uint8_t
など)を持つ必要があります。printf
フォーマットプレースホルダーはありません。固定幅の整数をフォーマットする必要がある場合は、uintmax_t
または intmax_t
にキャストしてください。char
%hhu
%hhd
int
n/a %d
(u)intmax_t
%ju
%jd
(s)size_t
%zu
%zd
ptrdiff_t
%tu
%td
bool
を使用します。int loaded = 1; // ❌: loaded should have type bool.
if (1 == x) {
if (x == 1) { //use this order
if ((x = f()) && (y = g())) {
static void f(void);
static void f(void)
{
...
}
<HEADER>
<PUBLIC FUNCTION DEFINITIONS>
<STATIC FUNCTION DEFINITIONS>
.c.generated.h
で終わり、*.h.generated.h
ファイルには非静的関数の宣言のみが含まれています。// src/nvim/foo.c file
#include <stddef.h>
typedef int FooType;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "foo.c.generated.h"
#endif
…
// src/nvim/foo.h file
#pragma once
…
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "foo.h.generated.h"
#endif
sizeof(void *)
!= sizeof(int)
であることを覚えておいてください。ポインターサイズの整数が必要な場合は、intptr_t
を使用してください。int64_t
/ uint64_t
メンバーを持つクラス/構造体は、デフォルトで64ビットシステムでは8バイトアラインメントになります。このような構造体を32ビットと64ビットのコード間でディスク上で共有する場合は、両方のアーキテクチャで同じようにパックされていることを確認する必要があります。ほとんどのコンパイラーは構造体のアラインメントを変更する方法を提供しています。gcc の場合は、__attribute__((packed))
を使用できます。MSVC では、#pragma pack()
と __declspec(align())
を提供しています。LL
または ULL
サフィックスを使用します。例:int64_t my_value = 0x123456789LL;
uint64_t my_mask = 3ULL << 48;
sizeof ~sizeof(type)
よりも sizeof(varname)
を優先します。sizeof(varname)
を使用します。sizeof(varname)
は、誰かが変数型を現在または後で変更した場合に適切に更新されます。外部または内部データ形式を管理するコードなど、適切な C 型の変数が便利ではない特定の変数に関係のないコードには、sizeof(type)
を使用できます。Struct data;
memset(&data, 0, sizeof(data));
memset(&data, 0, sizeof(Struct));
if (raw_size < sizeof(int)) {
fprintf(stderr, "compressed record not big enough for count: %ju", raw_size);
return false;
}
int price_count_reader; // No abbreviation.
int num_errors; // "num" is a widespread convention.
int num_dns_connections; // Most people know what "DNS" stands for.
int n; // Meaningless.
int nerr; // Ambiguous abbreviation.
int n_comp_conns; // Ambiguous abbreviation.
int wgc_connections; // Only your group knows what this stands for.
int pc_reader; // Lots of things can be abbreviated "pc".
int cstmr_id; // Deletes internal letters.
_
)を含めることができます。my_useful_file.c getline_fix.c // ✅: getline refers to the glibc function.C ファイルは
.c
で終わり、ヘッダーファイルは .h
で終わる必要があります。/usr/include
に既に存在するファイル名(db.h
など)は使用しないでください。logs.h
ではなく http_server_logs.h
を使用します。MyExcitingStruct
。struct my_exciting_struct
。struct my_struct {
...
};
typedef struct my_struct MyAwesomeStruct;
my_exciting_local_variable
。string table_name; // ✅: uses underscore.
string tablename; // ✅: all lowercase.
string tableName; // ❌: mixed case.
struct url_table_properties {
string name;
int num_entries;
}
g_
をプレフィックスとして付けます。k
に続けて、混合ケースを使用します:kDaysInAWeek
。k
に続けて、各単語の先頭を大文字にした単語を使用します。const int kDaysInAWeek = 7;
my_exceptional_function()
。同じヘッダーファイル内のすべての関数は、共通のプレフィックスを持つ必要があります。os_unix.h
の場合void unix_open(const char *path);
void unix_user_id(void);
関数がエラー時にクラッシュする場合は、関数名の末尾にor_die
を追加する必要があります。これは、製品コードで使用される可能性のある関数、および通常の動作中に発生する可能性のあるエラーにのみ適用されます。kEnumName
。enum url_table_errors {
kOK = 0,
kErrorOutOfMemory,
kErrorMalformedInput,
};
MY_MACRO_THAT_SCARES_CPP_DEVELOPERS
。#define ROUND(x) ...
#define PI_ROUNDED 5.0
//
スタイルの構文のみを使用してください。// This is a comment spanning
// multiple lines
f();
.h
ファイルは、ファイル内で宣言されている変数と関数が何のためにあり、どのように使用されるかの概要を説明します。.c
ファイルは、実装の詳細やトリッキーなアルゴリズムに関する議論を含む必要があります。実装の詳細やアルゴリズムに関する議論が.h
を読んでいる人にとって役立つと感じた場合は、代わりにそこに配置しても構いませんが、ドキュメントが.h
ファイルにあることを.c
で言及してください。.h
と.c
の両方でコメントを複製しないでください。複製されたコメントは乖離します。/// A brief description of this file.
///
/// A longer description of this file.
/// Be very generous here.
/// Window info stored with a buffer.
///
/// Two types of info are kept for a buffer which are associated with a
/// specific window:
/// 1. Each window can have a different line number associated with a
/// buffer.
/// 2. The window-local options for a buffer work in a similar way.
/// The window-info is kept in a list at g_wininfo. It is kept in
/// most-recently-used order.
struct win_info {
/// Next entry or NULL for last entry.
WinInfo *wi_next;
/// Previous entry or NULL for first entry.
WinInfo *wi_prev;
/// Pointer to window that did the wi_fpos.
Win *wi_win;
...
};
フィールドコメントが短い場合は、フィールドの横に配置することもできます。ただし、1つの構造体内で一貫性を保ち、必要なdoxygenスタイルに従ってください。struct wininfo_S {
WinInfo *wi_next; ///< Next entry or NULL for last entry.
WinInfo *wi_prev; ///< Previous entry or NULL for first entry.
Win *wi_win; ///< Pointer to window that did the wi_fpos.
...
};
ファイルの先頭のコメントで構造体を詳細に説明済みの場合は、「詳細については、ファイルの先頭のコメントを参照してください」と簡単に記述してもかまいませんが、何らかのコメントを必ず記述してください。/// Brief description of the function.
///
/// Detailed description.
/// May span multiple paragraphs.
///
/// @param arg1 Description of arg1
/// @param arg2 Description of arg2. May span
/// multiple lines.
///
/// @return Description of the return value.
Iterator *get_iterator(void *arg1, void *arg2);
.h
ファイルなど、関数宣言に付与されたコメントを繰り返すだけではいけません。関数が何をするかを簡単に要約するのは構いませんが、コメントの焦点はそれがどのように行うかに焦点を当てる必要があります。// Note that we don't use Doxygen comments here.
Iterator *get_iterator(void *arg1, void *arg2)
{
...
}
/// The total number of tests cases that we run
/// through in this regression test.
const int kNumTestCases = 6;
// If we have enough memory, mmap the data portion too.
mmap_budget = max<int64>(0, mmap_budget - index_->length());
if (mmap_budget >= data_size_ && !MmapData(mmap_chunk_bytes, mlock)) {
return; // Error already logged.
}
do_something(); // Comment here so the comments line up.
do_something_else_that_is_longer(); // Comment here so there are two spaces between
// the code and the comment.
{ // One space before comment when opening a new scope is allowed,
// thus the comment lines up with the following comments and code.
do_something_else(); // Two spaces before line comments normally.
}
bool success = calculate_something(interesting_value,
10,
false,
NULL); // What are these arguments??
bool success = calculate_something(interesting_value,
10, // Default base value.
false, // Not the first time we're calling this.
NULL); // No callback.
const int kDefaultBaseValue = 10;
const bool kFirstTimeCalling = false;
Callback *null_callback = NULL;
bool success = calculate_something(interesting_value,
kDefaultBaseValue,
kFirstTimeCalling,
null_callback);
// Now go through the b array and make sure that if i occurs,
// the next element is i+1.
... // Geez. What a useless comment.
TODO
コメントを使用します。TODO
には、すべて大文字でTODO
という文字列を含める必要があり、その後に、TODO
が参照する問題に関するコンテキストを最もよく提供できる人の名前、メールアドレス、またはその他の識別子を続けます。主な目的は、リクエストに応じて詳細を提供できる人を見つけるために検索できる一貫性のあるTODO
形式を持つことです。TODO
は、参照されている人が問題を修正するという約束ではありません。したがって、TODO
を作成するときは、ほとんどの場合、あなたの名前が付けられます。// TODO([email protected]): Use a "*" here for concatenation operator.
// TODO(Zeke): change this to use relations.
TODO
が「将来、何かをする」という形式の場合は、非常に具体的な日付(「2005年11月までに修正」)または非常に具体的なイベント(「すべてのクライアントがXML応答を処理できるようになったら、このコードを削除」)を含めるようにしてください。@deprecated
docstringトークンをマークします。@deprecated
という単語をすべて大文字で含むコメントを記述することで、インターフェースを非推奨としてマークできます。コメントは、インターフェースの宣言の前、または宣言と同じ行に記述します。@deprecated
の後には、名前、メール、またはその他の識別子を括弧内に記述します。DEPRECATED
とマークしても、コールサイトが魔法のように変更されるわけではありません。非推奨の機能を実際に使用させたくない場合は、自分でコールサイトを修正するか、手伝ってくれるクルーを募集する必要があります。"\uFEFF"
はUnicodeのゼロ幅ノーブレークスペース文字であり、UTF-8として直接ソースに含めると非表示になります。{
の後に1つのスペース、}
の前に1つのスペースを配置します。{}
がその名前の関数呼び出しの括弧であるかのようにフォーマットします。名前がない場合は、長さがゼロの名前を想定します。struct my_struct m = { // Here, you could also break before {.
superlongvariablename1,
superlongvariablename2,
{ short, interior, list },
{ interiorwrappinglist,
interiorwrappinglist2 } };
default
ケースが必要です(列挙値の場合、値が処理されない場合はコンパイラによって警告されます)。デフォルトケースが実行されるべきではない場合は、abort()
を使用するだけです。switch (var) {
case 0:
...
break;
case 1:
...
break;
default:
abort();
}
列挙値で条件付けられているswitchステートメントは、網羅的である場合はdefault
ケースを持つべきではありません。明示的なケースラベルは、同じコードに対して複数のケースラベルにつながる場合でも、default
よりも優先されます。たとえば、代わりにcase A:
...
case B:
...
case C:
...
default:
...
次を使用する必要がありますcase A:
...
case B:
...
case C:
...
case D:
case E:
case F:
...
一部のコンパイラは、網羅的な列挙型switchステートメントを網羅的として認識しないため、switchステートメントのすべてのケースにreturnステートメントがあるが、包括的なreturnステートメントがない場合にコンパイラの警告が発生します。これらの偽の誤りを修正するには、switchステートメントの後でUNREACHABLE
を使用して、switchステートメントが常に戻り、その後にあるコードは到達不能であることをコンパイラに明示的に伝えることをお勧めします。例:enum { A, B, C } var;
...
switch (var) {
case A:
return 1;
case B:
return 2;
case C:
return 3;
}
UNREACHABLE;
return
式を不必要に括弧で囲まないでください。return expr
で括弧を使用するのは、`x = expr;`で使用する場合のみです。return result;
return (some_long_condition && another_condition);
return (value); // You wouldn't write var = (value);
return(result); // return is not a function!
int long_variable = 0; // Don't align assignments.
int i = 1;
struct my_struct { // Exception: struct arrays.
const char *boy;
const char *girl;
int pos;
} my_variable[] = {
{ "Mia", "Michael", 8 },
{ "Elizabeth", "Aiden", 10 },
{ "Emma", "Mason", 2 },
};