Skip to content

Commit dee7b6d

Browse files
committed
コメント/マジックコメントの説明ページを新設する
行コメント・埋め込みドキュメント(=begin/=end)・マジックコメント (encoding, frozen_string_literal, warn_indent, shareable_constant_value)を 1ページにまとめた doc/spec/comment.md を新設し、doc/index.md の目次に追加する。 エンコーディング指定のみ1行目(shebang があれば2行目)限定で、他は実行コード より前ならコメント行の後でも認識される、という差異も明記(Ruby 3.4 で挙動確認)。 - doc/spec/lexical.md のコメント節から新ページへ相互リンク - doc/spec/m17n.md は encoding 以外のマジックコメントの入口として誘導 - doc/glossary.md のマジックコメント項に shareable_constant_value を追加し参照先を更新 - doc/news/3_0_0.md の壊れていた参照(m17n#magic_comment に未収録)を spec/comment#shareable_constant_value へ修正 fix rurema#2508
1 parent af4af5f commit dee7b6d

6 files changed

Lines changed: 263 additions & 5 deletions

File tree

manual/doc/glossary.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,9 +1585,13 @@
15851585
スクリプトエンコーディングを示すもの(encoding)、
15861586
文字列リテラルを凍結するかどうかを指定するもの(frozen_string_literal)、
15871587
インデント不整合の警告を出すかどうかを指定するもの(warn_indent)
1588-
がある。
1588+
#@since 3.0
1589+
、定数を Ractor で共有可能にするもの(shareable_constant_value)などがある。
1590+
#@else
1591+
などがある。
1592+
#@end
15891593

1590-
参照:[ref:d:spec/m17n#magic_comment]
1594+
参照:[ref:d:spec/comment#magic_comment]
15911595

15921596
- **ミックスイン**:
15931597
- **`mix-in`**:

manual/doc/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Ruby でのオブジェクト:
7272

7373
Ruby の文法:
7474
- [d:spec/lexical]
75+
- [d:spec/comment]
7576
- [d:spec/program]
7677
- [d:spec/variables]
7778
- [d:spec/literal]

manual/doc/news/3_0_0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def square(x) = x * x
8181
- # frozen-string-literal: true が使用されている場合、式展開を含む文字列リテラルは freeze されなくなりました。
8282
[feature:17104]
8383
- 定数を freeze するためのマジックコメント shareable_constant_value が導入されました。
84-
詳細は [ref:d:spec/m17n#magic_comment] を参照してください。
84+
詳細は [ref:d:spec/comment#shareable_constant_value] を参照してください。
8585
[feature:17273]
8686
- 静的解析基盤が導入されました。
8787
- RBS が導入されました。

manual/doc/spec/comment.md

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# コメント
2+
3+
- [ref:line_comment]
4+
- [ref:embedded_document]
5+
- [ref:magic_comment]
6+
- [ref:encoding]
7+
- [ref:frozen_string_literal]
8+
- [ref:warn_indent]
9+
#@since 3.0
10+
- [ref:shareable_constant_value]
11+
#@end
12+
13+
Ruby のコメントには、`#` から行末までを対象とする行コメントと、
14+
`=begin` から `=end` までの行を対象とする埋め込みドキュメントの
15+
2 種類があります(字句規則については [ref:d:spec/lexical#comment] も参照してください)。
16+
17+
また、ソースファイルの先頭に書かれた特定の形式のコメントは「マジックコメント」
18+
と呼ばれ、通常のコメントとは違い、Ruby の処理系に対してエンコーディングの
19+
指定や文字列リテラルの扱いなどを伝える働きを持ちます。
20+
21+
### 行コメント {#line_comment}
22+
23+
```ruby title="例"
24+
# これは行コメントです。
25+
p 1 + 1 # 式の後ろに書いたコメントです。
26+
```
27+
28+
`#` から行末まではコメントとみなされ、Ruby インタプリタからは無視されます。
29+
ただし文字列リテラルの中の `#` や、`?#` という文字リテラルの `#`
30+
コメントの開始とはみなされません。
31+
32+
### 埋め込みドキュメント(`=begin``=end`) {#embedded_document}
33+
34+
```ruby title="例"
35+
=begin
36+
ここから =end のある行までは
37+
複数行にわたるコメント(埋め込みドキュメント)になります。
38+
=end
39+
puts "hello"
40+
```
41+
42+
行頭(桁 0、インデントなし)から始まる `=begin` の行から、同じく行頭から
43+
始まる `=end` の行までの間はまとめてコメントとして扱われ、Ruby インタプリ
44+
タからは無視されます。`=begin``=end` はどちらもインデントすると
45+
埋め込みドキュメントとして認識されず、構文エラーになります。
46+
47+
```text title="インデントすると構文エラーになる例"
48+
x = 1
49+
=begin
50+
この =begin はインデントされているため
51+
埋め込みドキュメントの開始として認識されません。
52+
=end
53+
```
54+
55+
`=begin``=end` の行には、続けて自由な文字列を書くこともできます
56+
(その部分も無視されます)。
57+
58+
```ruby title="例"
59+
=begin タイトルなど自由に書けます
60+
本文
61+
=end 任意の文字列
62+
puts "hello"
63+
```
64+
65+
Ruby インタプリタは埋め込みドキュメントの中身の書式を規定しませんが、
66+
慣習として RD 形式で書かれることが期待されています。
67+
68+
### マジックコメントとは {#magic_comment}
69+
70+
マジックコメントとは、ソースファイルの先頭部分に書かれた特定の形式の
71+
コメントのことで、Ruby の処理系に対してそのファイルの解釈方法に関する
72+
指示を伝えるものです。通常のコメントと違い、書ける位置と書き方の形式が
73+
決まっています。
74+
75+
- マジックコメントが効果を持つのは、それが書かれたファイル自身に
76+
対してだけです。`require`/`load` で読み込む他のファイルや、
77+
`eval` で評価する文字列には影響しません。
78+
- ソースコード(実際に実行されるコード)より前に書かれている必要が
79+
あります。一度でも実行コードが出現した後に書いても無視されます。
80+
- ファイルの 1 行目が `#!` から始まる shebang 行
81+
([ref:d:spec/rubycmd#shebang]) である場合、マジックコメントは
82+
2 行目以降から探されます。
83+
84+
現在 Ruby が認識するマジックコメントには以下のものがあります。
85+
86+
- エンコーディングの指定([ref:encoding])
87+
- 文字列リテラルの凍結([ref:frozen_string_literal])
88+
- インデント不整合の警告([ref:warn_indent])
89+
#@since 3.0
90+
- 定数の Ractor 共有可能化([ref:shareable_constant_value])
91+
#@end
92+
93+
このうち、エンコーディングの指定だけは特別扱いされていて、ファイルの
94+
1 行目(shebang がある場合は 2 行目)に厳密に書かれている必要があります。
95+
空行や他のコメント行を挟んだ位置に書いても認識されません。
96+
97+
#@since 3.0
98+
それ以外のマジックコメント(frozen_string_literal, warn_indent,
99+
shareable_constant_value)は、実行コードより前であれば、複数のコメント行
100+
や空行、`=begin``=end` を挟んだ後に書いても認識されます。
101+
#@else
102+
それ以外のマジックコメント(frozen_string_literal, warn_indent)は、実行
103+
コードより前であれば、複数のコメント行や空行、`=begin``=end` を挟んだ
104+
後に書いても認識されます。
105+
#@end
106+
107+
```ruby title="例(frozen_string_literalは複数のコメント行の後でも認識される)"
108+
# ファイルの説明などの通常のコメント
109+
# 続きのコメント
110+
111+
# frozen_string_literal: true
112+
p "abc".frozen? #=> true
113+
```
114+
115+
複数のマジックコメントを、emacs のモードライン形式でまとめて 1 行に
116+
書くこともできます。
117+
118+
```ruby title="例"
119+
# -*- coding: utf-8; frozen_string_literal: true -*-
120+
p __ENCODING__ #=> #<Encoding:UTF-8>
121+
p "abc".frozen? #=> true
122+
```
123+
124+
### エンコーディングの指定 {#encoding}
125+
126+
```ruby title="例"
127+
# coding: euc-jp
128+
p __ENCODING__ #=> #<Encoding:EUC-JP>
129+
```
130+
131+
ソースファイルのエンコーディング(スクリプトエンコーディング)を指定
132+
します。以下のいずれの書き方でも認識されます。
133+
134+
```text
135+
# encoding: euc-jp
136+
# coding: euc-jp
137+
# -*- coding: euc-jp -*-
138+
```
139+
140+
Ruby 2.0 以降、マジックコメントが無い場合のデフォルトのスクリプト
141+
エンコーディングは UTF-8 です(Ruby 1.9 では US-ASCII でした)。
142+
143+
マジックコメントが指定されなかった場合の決定規則(コマンドライン引数
144+
や shebang との優先順位など)や、shebang 行がある場合の書き方など、
145+
より詳しい内容については [ref:d:spec/m17n#magic_comment] を参照して
146+
ください。[c:Encoding] クラス、[m:Encoding.default_external]
147+
参照してください。
148+
149+
### 文字列リテラルの凍結(`frozen_string_literal`) {#frozen_string_literal}
150+
151+
```ruby title="例"
152+
# frozen_string_literal: true
153+
154+
s = "abc"
155+
p s.frozen? #=> true
156+
157+
begin
158+
s << "d"
159+
rescue => e
160+
p e.class #=> FrozenError
161+
end
162+
```
163+
164+
`true` を指定すると、そのファイル内の文字列リテラルから生成される
165+
[c:String] オブジェクトが、生成された時点であらかじめ freeze された
166+
状態になります。`false`(指定しなかった場合のデフォルト)では、この
167+
機能は無効です。
168+
169+
この設定はファイル単位で有効になります。`require`/`load` で読み込んだ
170+
他のファイルの文字列リテラルや、`eval` で評価した文字列リテラルには
171+
影響しません。
172+
173+
```ruby title="例(require先やevalには伝播しない)"
174+
# frozen_string_literal: true
175+
eval('p "abc".frozen?') #=> false
176+
```
177+
178+
freeze されていないコピーが必要な場合は [m:Object#dup] や単項演算子
179+
`+`([m:String#+@])が、明示的に freeze したコピーが必要な場合は
180+
単項演算子 `-`([m:String#-@])が使えます。
181+
182+
### インデント不整合の警告(`warn_indent`) {#warn_indent}
183+
184+
```ruby title="例"
185+
# warn_indent: true
186+
187+
def foo
188+
if true
189+
puts "x"
190+
end # if に対して end のインデントの深さが揃っていない
191+
end
192+
```
193+
194+
```console
195+
$ ruby -w indent.rb
196+
indent.rb:6: warning: mismatched indentations at 'end' with 'if' at 4
197+
```
198+
199+
`end` と、それに対応するキーワード(`if` など)とでインデントの深さが
200+
異なる場合に警告を出すかどうかを指定します。この警告自体はデフォルトで
201+
有効になっていますが、実際に表示されるのは `-w` オプションや `-W2`
202+
を指定して実行した場合(`$VERBOSE` が true の場合)に限られます。
203+
204+
`# warn_indent: false` と指定すると、`-w`/`-W2` を指定して実行した
205+
場合でもこの警告を抑制できます。意図的に特殊なインデントを使うコード
206+
(DSL やコード生成物など)で警告を消したい場合に使われます。
207+
208+
#@since 3.0
209+
### 定数の Ractor 共有可能化(`shareable_constant_value`) {#shareable_constant_value}
210+
211+
```ruby title="例"
212+
# shareable_constant_value: literal
213+
214+
FOO = {a: 1, b: [1, 2, 3]}
215+
p Ractor.shareable?(FOO) #=> true
216+
p FOO.frozen? #=> true
217+
```
218+
219+
このマジックコメントより後にある定数への代入について、その値をどこまで
220+
自動的に [c:Ractor] で共有可能([m:Ractor.shareable?])にするかを指定します。
221+
以下のいずれかを指定します。
222+
223+
- **`none`**(デフォルト): 何もしません。通常通りの代入を行います。
224+
- **`literal`**: 代入される値がリテラルであり、かつその中身も再帰的に
225+
共有可能な値だけからなる場合に、freeze して共有可能にします。
226+
- **`experimental_everything`**: 代入される値がリテラルであるかに
227+
関わらず、[m:Ractor.make_shareable] を使って共有可能にします
228+
(実験的機能)。
229+
- **`experimental_copy`**: `experimental_everything` と同様ですが、
230+
共有可能でない値の場合、元のオブジェクトを直接 freeze するのでは
231+
なく、コピーしてから freeze して共有可能にします([m:Ractor.make_shareable]
232+
`copy: true` に相当、実験的機能)。
233+
234+
```ruby title="例(experimental_copyは代入前にコピーを作る)"
235+
# shareable_constant_value: experimental_copy
236+
237+
obj = Object.new
238+
FOO = obj
239+
p Ractor.shareable?(FOO) #=> true
240+
p FOO.equal?(obj) #=> false (コピーされている)
241+
```
242+
#@end

manual/doc/spec/lexical.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ Rubyの識別子は英文字またはアンダースコア('_')か
3535
スクリプト言語の習慣にならい、文字列中や文字リテラル `?#` 以外の
3636
\#から行末までをコメントと見なします。
3737

38+
コメントの詳細やマジックコメント(ファイル先頭の特別な形式のコメント)
39+
については [d:spec/comment] を参照してください。
40+
3841
### 埋め込みドキュメント {#embed}
3942

4043
```text title="例"
@@ -48,7 +51,7 @@ Rubyのソースコードにドキュメントを埋め込む事ができます
4851
始まる部分の行頭の=beginから、=endで始まる行までが
4952
埋め込みドキュメントです。Ruby インタプリタとしては内容に縛りは
5053
かけませんが、通常は RD 形式でドキュメントを埋め込むことを
51-
期待しています。
54+
期待しています(詳細は [d:spec/comment] を参照してください)
5255

5356
### 予約語 {#reserved}
5457

manual/doc/spec/m17n.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,15 @@ p __ENCODING__ #=> #<Encoding:EUC-JP>
169169
```
170170

171171
という形式のコメントのことです。1 行目が shebang である場合、マジックコメントは 2 行目に
172-
書くことができます(それ以降の行ではいけません。無視されます)。上の形式以外にも
172+
書くことができます(それ以降の行ではいけません。無視されます)。
173+
174+
エンコーディング指定以外にも、文字列リテラルの凍結(frozen_string_literal)
175+
やインデント不整合の警告(warn_indent)などを指定するマジックコメントが
176+
あります。これらは上のエンコーディング指定と異なり、1 行目(または shebang
177+
の次の行)以降のコメント行に書いても認識されます。マジックコメント全般に
178+
ついては [d:spec/comment] を参照してください。
179+
180+
上の形式以外にも
173181

174182
```text
175183
# encoding: euc-jp

0 commit comments

Comments
 (0)