---
title: architecture/reserved-name-placement · 予約名の配置
description: 予約ディレクトリ名は、その名前について宣言した場所にしか現れてはいけません。
---

**重大度:** info · **カテゴリ:** architecture

## チェック内容

予約ディレクトリ名が、その名前について宣言したどの位置にもマッチしない場所に現れている箇所を検出
します。`parts` について宣言したどの場所にも当てはまらないところに `parts/` が現れる、といった
ケースです。

このルールは**設定するまで無効**です。3 つの配置マップはすべて既定で `{}` です。

## なぜ重要か

`architecture/reserved-directory-names` は**「この位置では、これらの名前だけ」**と言います。これは
**「この名前は、これらの位置だけ」**とは言えません。複数の種類の場所(ユニットの直下、グルーピング
ディレクトリの直下、ルートディレクトリの直下)に同時に許可される名前について、姉妹ルールは他のどこかに
現れたコピーについて何も言えないからです。1 つの場所のために予約された名前は、別の場所に現れた瞬間に
その意味を失います。1 つの例外に出会った読み手は、そのディレクトリが何を持っているかを知るために
毎回中を開かなければならなくなります。

## 修正方法

ディレクトリをその名前について宣言済みの場所のいずれかに移動するか、リネームするか、この場所をその
名前について宣言してください。

## 設定

| オプション                  | 型                                                                                            | デフォルト |
| --------------------------- | --------------------------------------------------------------------------------------------- | ---------- |
| `placements`                | 予約名 → **親ディレクトリ**にマッチする `\|` 区切りの glob のマップ                           | `{}`       |
| `capitalisedUnitPlacements` | 予約名 → 直下に置ける**大文字始まりのユニット**ディレクトリにマッチする glob のマップ         | `{}`       |
| `anyCaseUnitPlacements`     | 予約名 → 直下に置ける**大文字小文字を問わないユニット**ディレクトリにマッチする glob のマップ | `{}`       |
| `exclude`                   | ディレクトリ glob のリスト                                                                    | `[]`       |

```js svelte-vitals.config.js
export default {
  rules: {
    'architecture/reserved-name-placement': {
      options: {
        // 名前が A–Z で始まり同名の子ファイルを持つユニットの直下
        capitalisedUnitPlacements: { parts: 'src/**', styleGuide: 'src/**' },
        // 大文字小文字を問わないユニットの直下
        anyCaseUnitPlacements: {
          tests: 'src/**',
          functions: 'src/**',
          stores: 'src/**',
          types: 'src/**'
        },
        // 親ディレクトリ自体を glob で指定
        placements: {
          functions: 'src/lib/features/*|src/lib/features/*/*|src/routes/**',
          stores: 'src/lib/features/*|src/lib/features/*/*',
          types: 'src/lib/features/*|src/lib/features/*/*|src/lib/db',
          e2e: 'src/routes|src/routes/**',
          components: 'src/routes|src/routes/**|src/lib'
        },
        exclude: ['src/lib/api/**']
      }
    }
  }
};
```

### 3 つのマップはすべて同じディレクトリにマッチする

3 つとも予約名の**親**ディレクトリにマッチし、違いはそのディレクトリにさらに何を求めるかだけです。
`placements` はそれ以上何も求めず、`capitalisedUnitPlacements` はそれが名前 A–Z で始まり同名の子
ファイルを持つユニットであることを求め(`architecture/reserved-directory-names` の `isUnitDir`)、
`anyCaseUnitPlacements` は文字の条件を除いた同じ判定を求めます。

### 位置は 3 つのマップの和集合

ある名前が許可される位置は、3 つのマップにまたがるエントリの**和集合**です。どのマップにも現れない
名前は対象になりません。上の例で `functions` が `anyCaseUnitPlacements` と `placements` の両方に
現れているのはこのためです。実際の規約は、1 つの名前をユニットの直下・グルーピングディレクトリの直下・
ルートディレクトリの直下に同時に許可することがあり、各名前がちょうど 1 つのマップにしか属せない設計
では、それを表現できません。

### `|` で選択肢を区切り、空の値は名前全体を対象外にする

値は `|` 区切りの glob のリストで、そのいずれか 1 つがその位置を許可すれば十分です。分割した結果が
空になる値、たとえば `placements: { e2e: '|' }` は、それを持つマップだけでなく**すべてのマップでその
名前を対象外にし**、かつ報告されます。空の値だけを落とすと和集合が縮んでしまい、書き間違いが、
その空になったエントリが担っていたすべての位置で偽陽性に変わってしまいます。

### ユニットマップの素の glob はユニット自身にマッチする

`capitalisedUnitPlacements` と `anyCaseUnitPlacements` は、名前が直下に置かれる**ユニット
ディレクトリ自体**にマッチし、その下にあるだけの祖先にはマッチしません。したがって
`parts: 'src/lib'` は、ちょうど `src/lib` にあるユニットの直下でしか `parts/` を許可しません。
`lib` は小文字なので capitalised マップでは到達不能です。一方 `parts: 'src/lib/**'` は
`src/lib` 配下のどのユニットの直下でも許可します。素の glob が到達するのは、それが指す 1 つの
ディレクトリだけです。読み手が「このパス配下のどのユニットでも」という意味で書いた場合は間違いに
なります。`src/lib` は capitalised マップでは決してユニットになり得ないため、報告されます。
読み手が意図してその 1 つの実在するユニットを指定した場合は正しく、報告されません。
`parts: 'src/lib/Card'` は、ちょうど `src/lib/Card` にあるユニットの直下でのみ `parts/` を許可
し、`parts/` がそこにある限り finding は生じません。`src/lib` ではなく `src/lib/**` と書くべき
なのは、前者の場合だけです。

### `exclude`

`exclude` は、姉妹ルールと同様に、ディレクトリとその配下すべてを対象から除外します。下で述べる宣言に
ついての診断は、`overrides` レイヤーが追加する `exclude` ではなく、設定ファイル自身が宣言した
`exclude` に照らして判定されます。配置違反の finding のほうはどちらも尊重します。`overrides`
レイヤーは除外の追加しかできないため、これによって診断が静かになることはあっても、うるさく
なることはありません。

## 制限

対象は `src/` 配下のディレクトリだけです。

宣言が書いてある内容を実際には検査していない場合は報告されるので、書き間違いでルールが黙って何も
しない状態にはなりません。finding にはその理由が名前で示されます。

- 値が**位置を 1 つも挙げていなかった**。この場合、その名前はすべてのマップで対象外になります。
- glob が**1 つのディレクトリにもマッチしなかった**。これはファイルシステムではなくソースの
  棚卸しに照らして判定されます。`src/` の外を指す glob や、ツリーに `src/routes` しかないのに
  `src/route/**` と書いてしまうような書き間違いは、そのディレクトリが実在していても「1 つの
  ディレクトリにもマッチしなかった」と報告されます。このルールは `src/` の外を一切見ないためです。
- glob が、`exclude` が除外せずに残したディレクトリに一度も到達しない。「マッチしたディレクトリは
  すべて除外されていた」として報告されます。生きているディレクトリにも到達する glob は、そのマッチの
  一部が除外されていても、ここでは報告されません。
- ユニットマップの glob が、求める大文字小文字の条件を満たすユニットに、`exclude` が除外せずに
  残したツリーのどこにも到達しない。「ユニットに一度も到達しない」として報告されます。これは上で
  述べた素の glob の書き間違いを実際に検出します。`parts: 'src/lib'` は capitalised ユニットに
  まったく到達しません(ちょうど `src/lib` にあるユニットは、`lib` が小文字なので到達不能だから
  です)。`src/lib` ではなく `src/lib/**` と書いてください。

ある名前が現れて**よい**場所を示す宣言は、それが使われていないからといって無効ではありません。
まだどのディレクトリも使っていない、正当だが現状空の位置は、意図的に何も報告しません。これは上の
どの場合にも当てはまりません。読み手が頼ってよい規則はこうです。宣言はその glob が実際に**到達
できるか**で判定されるのであって、たまたま行使したかどうかでは判定されません。まだどのディレクトリも
占めていない位置に対する正しい宣言は黙ったままであり、一方でユニットがまだ存在しないサブツリーに
絞った glob は、まだ存在しないディレクトリを指す glob と同じ扱いで、それでも報告されます。

このルールが意図的に扱わないものが 2 つあります。予約名ディレクトリでの過剰許可(同じ深さにある
グルーピングディレクトリと予約名ディレクトリを glob で区別できないため)と、ツリーから宣言を
生成することです。

## モードによる違い

ありません。このルールが読むのは、ファイル内容ではなくプロジェクトのソースファイル一覧（`src/**` のパス）です。この一覧は CLI、Vite プラグインのビルド、ライブダッシュボードの静的ベースラインのいずれでも同じように作られるため結果は同一で、レンダリング済み HTML の解析で再評価されることもありません。`--route` で実行範囲を絞ると、このルールは動きません。一覧が作られず、ファイルの検出には紐づけるルートも無いためです。

## 無効化

個別に抑制するには、対象行の直前に `<!-- svelte-vitals-disable-next-line architecture/reserved-name-placement -->` を置きます。ルールごと無効化するには、次のように設定します。

```js svelte-vitals.config.js
export default {
  rules: {
    'architecture/reserved-name-placement': 'off'
  }
};
```
