RFC-0086:RFC-0050 更新:FIDL 屬性語法 | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 以 FIDL 語言指定新的屬性語法。 |
問題 | |
毛皮變化 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2021-03-09 |
審查日期 (年-月-日) | 2021-04-07 |
摘要
本文件會說明新的 attributes 語法, FIDL 語言。
另請參閱:
提振精神
FIDL 屬性提供將編譯時間中繼資料附加至 FIDL 的明確方法 宣告,讓作者能夠將額外資訊傳遞至 FIDL 編譯器 相關文件 (文件、 NoDoc) 編譯時間驗證 (ForDeprecatedCBindings)、 程式碼生成 (轉換、 傳輸),所需的 API 可用性 (可供探索),以此類推。 「官方」屬性,FIDL 作者就可以定義自己的「自訂」 這類屬性不會影響編譯,但仍會附加至 產生 FIDL JSON Intermediate Representation, 使用。
現有屬性語法缺少三個屬性:
- 多個屬性是以逗號分隔的宣告
如下所示:
[Discoverable, NoDoc, Transport = "Channel"]
。這項做法缺乏彈性 因為屬性是彼此獨立的。 - 屬性目前只能接受 0 或一個引數,但
- 當屬性接受引數時,值一律為字串。例如:
MaxBytes 屬性採用字串化數字做為引數,如下所示:
[MaxBytes="128"]
。這會造成混淆,尤其是在 FIDL 的其他部分 都是可預測的字詞
系統目前將 FIDL 語法進行重大遷移, RFC-0050:語法更新工作。對他們來說 也可以變更屬性的語法
設計
語法
每個屬性都屬於單一宣告,其中包含屬性名稱
前方加上 @
符號 (以慣例為 lower_snake_cased)。適用對象
宣告包含多個屬性的宣告時,沒有偏好的排序方式
屬性。舉例來說,屬性宣告 [Discoverable,
NoDoc, Transport = "Channel"]
現在可以寫成:
@discoverable
@no_doc
@transport("Channel")
protocol P {};
如有必要,屬性名稱可視需要加上一組括號。 ,且包含一或多個引數的逗號分隔清單。引數可以是 任何有效的 FIDL 常數。例如:
const DEFAULT_TRANSPORT string = "Channel";
@transport(DEFAULT_TRANSPORT)
protocol P {};
引數必須以小寫的「關鍵字」表示與類似語法
在 Python 中找到的屬性,但針對
只需要加入一個引數,即可省略關鍵字。引數輸入和存在
只會驗證 fidlc 原生的屬性。適用對象
這類屬性,編譯器可能會預設省略對
預先定義的值請參考下列模擬 @native
的使用範例
屬性,該屬性需要兩個必要引數 (req_a
和 req_b
),以及兩個
選擇性參數(opt_a
和 opt_b
):
const C bool = true;
@native(req_a="Foo",req_b=3) // OK: neither opt arg is set
@native(req_a="Foo",req_b=3,opt_c=C) // OK: only opt_a is set
@native(req_a="Foo",req_b=3,opt_d=-4) // OK: only opt_b is set
@native(req_a="Foo",req_b=3,opt_c=C,opt_d=-4) // OK: both opt args are set
@native(req_a="Foo",req_b=3,opt_d=-4,opt_c=C) // OK: arg order is irrelevant
@native(opt_d=-4,req_a="Foo",req_b=3) // OK: arg order is irrelevant
@native(req_b=3) // Error: missing req_a
@native(req_a="Foo") // Error: missing req_b
type S = struct {};
作者定義的自訂屬性為無結構,且單純是以
並在 FIDL 檔案中運作編譯器無法驗證數字
及其正確型別
(不過當我們選擇導入「In-FIDL」屬性時,應會因此變更
如下所述
替代方案一節)。因此,
強制執行屬性簽章的文法正確性。範例
以下顯示作者定義屬性 @custom
:
@custom(a="Bar",b=true) // OK: grammatically correct
@custom("Bar",true) // Error: bad grammar - multiple args require keywords
@custom("Bar") // OK: correct grammar (though signature now unclear)
@custom(true) // OK: correct grammar (signature even more unclear)
@custom() // Error: bad grammar - cannot have empty arguments list
@custom // OK: grammatically correct
type S = struct {};
經修改後的新 FIDL 屬性的 BNF 文法 語法為:
attribute = "@", IDENTIFIER , ( "(" , constant | attribute-args, ")" ) ;
attribute-args = attribute-arg | attribute-arg, "," attribute-args;
attribute-arg = IDENTIFIER , "=" , constant;
RFC-0040:ID 唯一性適用於屬性名稱。這個 表示屬性名稱中不同的大小寫和連續底線 在正式名稱解析期間降為單一通用名稱。下列 因此,這樣會導致範圍衝突,在編譯期間產生錯誤:
@foo_bar
@FooBar // Error: re-used attribute name "foo_bar"
@fooBar // Error: re-used attribute name "foo_bar"
@Foo_Bar // Error: re-used attribute name "foo_bar"
@foo__bar // Error: re-used attribute name "foo_bar"
@FOOBar // Error: re-used attribute name "foo_bar"
type S = struct {};
JSON IR
屬性的 FIDL JSON 中介表示法結構定義
反映新的語法結構定義的屬性
definition 現在提供 location
欄位來追蹤
屬性宣告的檔案內位置。以下為「value
」欄位
會替換為 arguments
欄位,該欄位會將每個引數的值儲存為
name
/value
配對,而後者採用前者,
#/definitions/constant
。適用於只接受一個引數的屬性
來源中沒有關鍵字 name
,因此唯一的引數名稱會預設為
"value"
。
此外,compose
個段落和 reserved
資料表/工會成員是
不能攜帶屬性此 RFC 能解決這些疏忽
將新的 #/definitions/compose
定義新增為
#/definitions/interface
,並正式在
#/definitions/table-member
。
總之,這個 RFC 引入了三種新的結構定義定義
(#/definitions/attribute-arg
、#/definitions/attribute-args
和
#/definitions/compose
) 並另外修改了另外三種 (#/definitions/attribute
、
#/definitions/interface
和 #/definitions/table-member
)。新屬性
定義看起來會像這樣:
"attribute-arg": {
{
"description": "Definition of an attribute argument",
"type": "object",
"required": [
"name",
"value",
],
"properties": {
"name": {
"description": "Name of the attribute argument",
"type": "string",
},
"value": {
"description": "Value of the attribute argument",
"$ref": "#/definitions/constant",
},
"location": {
"description": "Source location of the attribute argument",
"$ref": "#/definitions/location"
},
},
},
},
"attribute-args": {
{
"description": "Definition of an attributes argument list",
"type": "array",
"items": {
"description": "List of arguments",
"$ref": "#/definitions/attribute-arg",
},
},
},
"attribute": {
{
"description": "Definition of an attribute",
"type": "object",
"required": [
"name",
"arguments",
"location",
],
"properties": {
"name": {
"description": "Attribute name",
"type": "string",
},
"arguments": {
"description": "Attribute arguments",
"$ref": "#/definitions/attribute-args",
},
"location": {
"description": "Source location of the declaration",
"$ref": "#/definitions/location",
},
},
},
},
"compose": {
{
"description": "Compose member of an interface declaration",
"type": "object",
"required": [
"name",
"location",
],
"properties": {
"name": {
"$ref": "#/definitions/compound-identifier",
"description": "Name of the composed interface"
},
"maybe_attributes": {
"description": "Optional list of attributes of the compose declaration",
"$ref": "#/definitions/attributes-list",
},
"location": {
"description": "Source location of the compose declaration",
"$ref": "#/definitions/location",
},
},
},
},
延續上一節的 @native
範例,
針對 type S
的 JSON IR 輸出內容,其 maybe_attributes
欄位會是:
"maybe_attributes": [
{
"name": "native",
"arguments": [
// Note: the omitted opt_d is not included in the IR
{
"name": "req_a",
"value": {
"kind": "literal",
"value": "Foo",
"expression": "\"Foo\"",
"value": {
"kind": "string",
"value": "Foo",
"expression": "\"Foo\"",
},
},
},
{
"name": "req_b",
"value": {
"kind": "literal",
"value": "3",
"expression": "3",
"literal": {
"kind": "numeric",
"value": "3",
"expression": "3",
},
},
},
{
"name": "opt_c",
"value": {
"kind": "identifier",
"value": "true",
"expression": "C",
"identifier": "example/C",
},
},
],
"location": {
"filename": "/path/to/src/fidl/file/example.fidl",
"line": 4,
"column": 0,
"length": 36,
},
},
],
個案研究:FIDL 版本管理
RFC-0083: FIDL 版本管理說明瞭
將版本管理中繼資料附加到 FIDL 宣告及其成員。於
也就是定義了新的屬性 @available
,該屬性採用的
platform
、since
、removed
、deprecated
和 note
引數。例如:
@available(since=2)
type User = table {
// Was created with struct at version 2, so no @available attribute is needed.
1: is_admin bool;
// Deprecated in favor of, and eventually replaced by, the name field.
@available(deprecated=3,removed=4,note="use UTF-8 `name` instead")
2: uid vector<uint8>;
// The current (unreleased) version constrains this definition.
// Placing "removed" before "since" is discouraged, but won't fail compilation.
@available(removed="HEAD",since=3)
3: name string;
@available(since="HEAD")
3: name string:60;
};
值得注意的是,引數會參照編號的平台版本
(例如 since
、removed
和 deprecated
) 也可以使用特殊字串
"HEAD"
。這表示這些引數不會只有一個也很容易
可解析的類型,例如 uint8
。這種建構項目是可以接受的,因為
特定的「官方」類型驗證規則@available
之類的屬性
寫死在編譯器本身中其他更細微的規則
限制只有 @available
個屬性附加至 library
宣告
可能會包含 platform
引數,也會以輪輻的方式處理。
實作
此提案將做為更廣泛的 RFC-0050 的一部分進行。 FIDL 語法轉換。所有以「new」記載的 FIDL 檔案語法將 以符合 RFC 的 文法將會隨之更新,反映其他方面的設計 RFC-0050。
此外,結構定義也會更新為 適用本文件指定的 JSON IR 變更。不過, 實際遷移至 語法,以確保 RFC-0050 定義 語法所產生的 IR 就像是驗證 正確性。因此,更新 attributes. 定義必須同時 再進行 RFC-0050 遷移作業,確保 JSON IR 並未變更 在這段期間。
成效
這類語法變更不太可能對效能造成影響。
安全性考量
這些語法變更不太可能會對安全性造成重大影響。確實 讓未來安全驗證屬性產生小衝擊 更容易撰寫及推理
隱私權注意事項
這些語法變更不太可能對隱私權造成重大影響。確實 未來可能在隱私權驗證屬性上導入潛在好處 更容易撰寫及推理
測試
這類語法變更不太可能會對測試造成重大影響。確實 在未來的測試檢測屬性中 增加潛在好處 更容易撰寫及推理
說明文件
所有相關文件和範例都將更新,加入新的 語法做為 RFC-0050 說明文件更新的一部分。於 請參閱官方 FIDL 的參考說明文件 屬性都將更新,以反映此設計所製定的規則。 注意每個屬性的有效引數類型和默示預設值。
缺點、替代方案與不明
In-FIDL 屬性結構定義
可用的語法幾乎是無限的設計空間。本節 不會試圖解決所有問題但有些選項 考慮允許定義註解函式的介面 「透過 FIDL」。這個替代語法及其拒絕原因 。
請參考以下 FIDL 檔案,該檔案含有其自訂屬性的介面 定義於內嵌:
type MyAttrArgs = table {
1: foo string;
2: bar int32;
3: baz bool;
};
@myAttr(MyAttrArgs{foo: "abc", bar: 1, baz: false})
type MyStruct = struct {...};
這個設計的優點在於「自行食用 Dogfood 測試:」FIDL 是介面 所以不必定義內建介面 以及編譯器感知屬性函式嗎?此外,這也意味著 建立自訂的使用者定義屬性。 編譯器會將這類使用者定義的中繼資訊, 產生的繫結程式碼依然是開放式問題
由於嘗試過多,這個設計路徑最終會遭到拒絕。以上皆非 在未來可預見的屬性中,屬性的使用情境必須 定義能力,而且這項功能尚未釐清 有利的未來目標本文件建議的語法為 對其他熱門程式語言 (例如 Rust 和 Python。
目前的設計中未明確排除 In-FIDL 實作項目 因此,這個替代方案仍是可行的 新增至屬性語法
在屬性引數中使用字串常值
針對本文件中指定的設計,其中一種可能的改變是 不必允許使用輸入的引數,也可以保留 所有引數值都屬於字串常值請參考以下範例 說明這類設計:
const MAX_STR string = "123";
const MAX_NUM uint64 = 123;
@max_handles(123) // Error: cannot use non-string types
@max_handles(MAX_STR) // Error: cannot use const identifiers
@max_handles(MAX_NUM) // Error: cannot use non-string types or const identifiers
@max_handles("123") // OK: only string literals are allowed
type S = struct {};
這項設計的缺點是易於實作的簡易實作。目的地:
容納型別的屬性引數,後端所需的
複雜的擷取邏輯可適當解讀各種可能的類型
定義每個屬性引數。先前簡單從
傳送至 int 123
的字串 "123"
已足夠,後端現在需要處理
整個 #/definitions/constant
結構定義中的一部分其他
將實作成本乘以支援的後端數量。
允許使用類型屬性的好處是能集中處理這類屬性
轉換邏輯。舉例來說,假設
@my_custom_attr("3.")
。如果每個後端都應該自行執行類型轉換
可能判定 "3."
是要轉換為整數的有效值,而另一個
則不一定。很難抓出這塊木頭的所有細節
後端的屬性導入作業
是難免的正在放大一個
使用 fidlc 屬性類型行為的正規知識。
不一致的情況
拒絕的輕微修改
本文件中描述的屬性語法會明確指出 單一宣告所附加的多個屬性之間的排序為 無關緊要。另一種做法是強制執行字母順序 順序。由於作者定義自訂屬性和 未來 fidlc 原生屬性可能會以其他可能的方式參照其他屬性 之所以能受惠於具體的排序方式嗎?請考量下列兩項做法 由作者定義的自訂屬性,但這些屬性的順序會令人混淆 如需要按字母順序排序:
@this_attr("Foo")
@test_for_this_attr(false)
protocol P {};
此外,我們也建議將駝峰式大小寫視為 屬性語法這項建議最終遭到拒絕,因為無 FIDL 樣式指南中的其他大小寫建議 而且在 1X 之後加入新的機器系列 屬性的大小寫樣式。
既有作品和參考資料
此 RFC 是 RFC-0050:語法 中定義的語法演變 修訂 ,進而修改正式的 FIDL 文法。
本提案以「歸因類」模型為基礎導入 特別是其他語言:
- Python 的裝飾器語法和
關鍵字引數設計有助於激發靈感
本文說明本文件採用的一些設計選項,例如使用
@
符號,以及參照每個關鍵字的引數。 - Rust 的屬性規格,而十分重要 某些語法選擇在概念上也類似 提案。
- Cap'n Proto 的註解結構定義 會視為更有用的替代方案 使用本文件提議的語法