github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/go/token/position.go (about)

     1  // Copyright 2010 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package token
     6  
     7  import (
     8  	"github.com/shogo82148/std/sync"
     9  	"github.com/shogo82148/std/sync/atomic"
    10  )
    11  
    12  // Positionはファイル、行、列の位置を含む任意のソース位置を表します。
    13  // Positionは行番号が> 0の場合に有効です。
    14  type Position struct {
    15  	Filename string
    16  	Offset   int
    17  	Line     int
    18  	Column   int
    19  }
    20  
    21  // IsValid は位置が有効かどうかを報告します。
    22  func (pos *Position) IsValid() bool
    23  
    24  // Stringはいくつかの形式で文字列を返します:
    25  //
    26  //	file:line:column    ファイル名を含む有効な位置
    27  //	file:line           ファイル名を含む有効な位置だが列がない(column == 0)
    28  //	line:column         ファイル名を含まない有効な位置
    29  //	line                ファイル名もなく列もない有効な位置(column == 0)
    30  //	file                ファイル名を含む無効な位置
    31  //	-                   ファイル名もない無効な位置
    32  func (pos Position) String() string
    33  
    34  // Posはファイルセット内のソース位置のコンパクトなエンコーディングです。
    35  // より便利ながらもはるかに大きい表現のために、[Position] に変換することができます。
    36  //
    37  // 与えられたファイルに対するPosの値は、[base、base+size]の範囲内の数値です。
    38  // baseとsizeは、ファイルがファイルセットに追加される際に指定されます。
    39  // Posの値と対応するファイルベースの差は、その位置(Posの値によって表される)からのバイトオフセットに対応します。
    40  // したがって、ファイルベースオフセットは、ファイル内の最初のバイトを表すPosの値です。
    41  //
    42  // 特定のソースオフセット(バイト単位で測定される)のPos値を作成するには、
    43  // まず [FileSet.AddFile] を使用して対応するファイルを現在のファイルセットに追加し、
    44  // そのファイルのために[File.Pos](offset)を呼び出します。
    45  // 特定のファイルセットfsetに対するPos値pを持つ場合、対応する [Position] 値はfset.Position(p)を呼び出すことで得られます。
    46  //
    47  // Pos値は通常の比較演算子を使って直接比較することができます:
    48  // 2つのPos値pとqが同じファイルにある場合、pとqを比較することは、対応するソースファイルのオフセットを比較することと等価です。
    49  // pとqが異なるファイルにある場合、qによって指定されるファイルがpによって指定されるファイルよりも前に対応するファイルセットに追加された場合、p < qはtrueです。
    50  type Pos int
    51  
    52  // [Pos] のゼロ値はNoPosであり、ファイルおよび行情報は関連付けられていません。
    53  // また、NoPos.IsValid()はfalseです。NoPosは常に他の [Pos] 値よりも小さくなります。
    54  // NoPosに対応する [Position] 値は [Position] のゼロ値です。
    55  const NoPos Pos = 0
    56  
    57  // IsValid は位置が有効かどうかを報告します。
    58  func (p Pos) IsValid() bool
    59  
    60  // Fileは、[FileSet] に属するファイルのハンドルです。
    61  // Fileには名前、サイズ、行オフセット表があります。
    62  type File struct {
    63  	name string
    64  	base int
    65  	size int
    66  
    67  	// lines と infos はミューテックスによって保護されています。
    68  	mutex sync.Mutex
    69  	lines []int
    70  	infos []lineInfo
    71  }
    72  
    73  // NameはAddFileで登録されたファイルfのファイル名を返します。
    74  func (f *File) Name() string
    75  
    76  // Baseは、AddFileで登録されたファイルfの基本オフセットを返します。
    77  func (f *File) Base() int
    78  
    79  // SizeはAddFileで登録されたファイルfのサイズを返します。
    80  func (f *File) Size() int
    81  
    82  // LineCount returns the number of lines in file f.
    83  func (f *File) LineCount() int
    84  
    85  // AddLineは新しい行の行オフセットを追加します。
    86  // 行オフセットは前の行のオフセットよりも大きく、ファイルのサイズよりも小さい必要があります。そうでない場合、行オフセットは無視されます。
    87  func (f *File) AddLine(offset int)
    88  
    89  // MergeLineは、次の行と行を結合します。これは、行の末尾の改行文字をスペースで置き換えることに似ています(残りのオフセットは変更されません)。行番号を取得するには、[Position.Line] などを参照してください。無効な行番号が指定された場合、MergeLineはパニックを起こします。
    90  func (f *File) MergeLine(line int)
    91  
    92  // Linesは [File.SetLines] で指定された形式の効果的な行オフセットの表を返します。
    93  // 呼び出し元は結果を変更してはいけません。
    94  func (f *File) Lines() []int
    95  
    96  // SetLinesはファイルの行オフセットを設定し、成功したかどうかを報告します。
    97  // 行オフセットとは、各行の最初の文字のオフセットです。
    98  // たとえば、"ab\nc\n"という内容の場合、行オフセットは{0、3}です。
    99  // 空のファイルは空の行オフセットテーブルを持ちます。
   100  // 各行のオフセットは、前の行のオフセットよりも大きく、ファイルサイズよりも小さくなければなりません。
   101  // それ以外の場合、SetLinesは失敗し、falseを返します。
   102  // SetLinesが返された後は、与えられたスライスを変更しないでください。
   103  func (f *File) SetLines(lines []int) bool
   104  
   105  // SetLinesForContentは与えられたファイルの内容に対して行のオフセットを設定します。
   106  // 位置を変更する//lineコメントは無視されます。
   107  func (f *File) SetLinesForContent(content []byte)
   108  
   109  // LineStartは指定された行の開始位置の [Pos] 値を返します。
   110  // [File.AddLineColumnInfo] を使用して設定された代替の位置は無視されます。
   111  // LineStartは、1ベースの行番号が無効な場合にパニックを引き起こします。
   112  func (f *File) LineStart(line int) Pos
   113  
   114  // AddLineInfoは、Column = 1引数を持つ [File.AddLineColumnInfo] と同様です。
   115  // Go 1.11より前のコードの後方互換性のためにここにあります。
   116  func (f *File) AddLineInfo(offset int, filename string, line int)
   117  
   118  // AddLineColumnInfoは、与えられたファイルオフセットに対して代替のファイル、行、および列番号の情報を追加します。オフセットは、以前に追加された代替の行情報のオフセットよりも大きく、ファイルサイズよりも小さい必要があります。それ以外の場合、情報は無視されます。
   119  // AddLineColumnInfoは通常、//line filename:line:columnなどの行ディレクティブの代替位置情報を登録するために使用されます。
   120  func (f *File) AddLineColumnInfo(offset int, filename string, line, column int)
   121  
   122  // Posは、指定されたファイルオフセットのPos値を返します。
   123  //
   124  // オフセットが負の場合、結果はファイルの開始位置です。
   125  // オフセットが大きすぎる場合、結果はファイルの終了位置です(go.dev/issue/57490も参照してください)。
   126  //
   127  // 一般的なPos値には当てはまらないが、結果pに対しては次の不変性が保持されます:
   128  // f.Pos(f.Offset(p)) == p.
   129  func (f *File) Pos(offset int) Pos
   130  
   131  // Offsetは、指定されたファイル位置pのオフセットを返します。
   132  //
   133  // pがファイルの開始位置より前(またはpがNoPos)の場合、結果は0です。
   134  // pがファイルの終了位置を過ぎている場合、結果はファイルサイズです(go.dev/issue/57490も参照してください)。
   135  //
   136  // 一般的なオフセット値には当てはまらないが、結果のオフセットに対しては次の不変性が保持されます:
   137  // f.Offset(f.Pos(offset)) == offset
   138  func (f *File) Offset(p Pos) int
   139  
   140  // Lineは与えられたファイル位置pの行番号を返します。
   141  // pはそのファイル内の [Pos] 値または [NoPos] でなければなりません。
   142  func (f *File) Line(p Pos) int
   143  
   144  // PositionForは、指定されたファイル位置pに対するPosition値を返します。
   145  // pが範囲外の場合、File.Offsetの動作に合わせて調整されます。
   146  // adjustedが設定されている場合、位置は位置を変更する
   147  // //lineコメントによって調整される可能性があります。それ以外の場合、それらのコメントは無視されます。
   148  // pはf内のPos値、またはNoPosでなければなりません。
   149  func (f *File) PositionFor(p Pos, adjusted bool) (pos Position)
   150  
   151  // Positionは、指定されたファイル位置pに対するPosition値を返します。
   152  // pが範囲外の場合、それはFile.Offsetの動作に合わせて調整されます。
   153  // f.Position(p)を呼び出すことは、f.PositionFor(p, true)を呼び出すことと同等です。
   154  func (f *File) Position(p Pos) (pos Position)
   155  
   156  // FileSetはソースファイルの集合を表します。
   157  // ファイルセットのメソッドは同期されており、複数のゴルーチンが同時に呼び出すことができます。
   158  //
   159  // ファイルセット内の各ファイルのバイトオフセットは、異なる(整数)間隔、すなわち間隔[base、base+size]にマッピングされます。 [FileSet.Base] はファイルの最初のバイトを表し、sizeは対応するファイルサイズです。 [Pos] 値はそのような間隔内の値です。 [Pos] 値が属する間隔を決定することで、ファイル、そのファイルのベース、そして [Pos] 値が表しているバイトオフセット(位置)を計算することができます。
   160  //
   161  // 新しいファイルを追加する際には、ファイルベースが必要です。それはすでにファイルセット内の任意のファイルの間隔の終わりを過ぎた整数値である必要があります。便宜上、 [FileSet.Base] はそのような値を提供します。それは単純に最後に追加されたファイルのPos間隔の終わりの位置に+1した値です。後で間隔を拡張する必要がない場合は、 [FileSet.Base] を [FileSet.AddFile] の引数として使用する必要があります。
   162  //
   163  // FileSetが不要な場合、 [File] はFileSetから削除することができます。これにより、長時間実行されるアプリケーションでメモリ使用量を削減することができます。
   164  type FileSet struct {
   165  	mutex sync.RWMutex
   166  	base  int
   167  	files []*File
   168  	last  atomic.Pointer[File]
   169  }
   170  
   171  // NewFileSetは新しいファイルセットを作成します。
   172  func NewFileSet() *FileSet
   173  
   174  // Baseは、次のファイルを追加する際に [FileSet.AddFile] に提供する必要がある最小のベースオフセットを返します。
   175  func (s *FileSet) Base() int
   176  
   177  // AddFileは、指定されたファイル名、ベースオフセット、ファイルサイズを持つ新しいファイルをファイルセットsに追加し、ファイルを返します。複数のファイルは同じ名前を持つことができます。ベースオフセットは、 [FileSet.Base] より小さくはならず、サイズは負であってはいけません。特別なケースとして、負のベースが提供された場合、 [FileSet.Base] の現在の値が代わりに使用されます。
   178  // ファイルを追加すると、次のファイルのための最小ベース値として、 [FileSet.Base] の値はbase + size + 1に設定されます。与えられたファイルオフセットoffsに対する [Pos] 値pの関係は次のとおりです:
   179  // int(p) = base + offs
   180  // ただし、offsは範囲[0、size]にあり、したがってpは範囲[base、base+size]にあります。便宜上、 [File.Pos] はファイル固有の位置値をファイルオフセットから作成するために使用できます。
   181  func (s *FileSet) AddFile(filename string, base, size int) *File
   182  
   183  // RemoveFileは、 [FileSet] からファイルを削除し、その後の [Pos] 間隔のクエリが負の結果を返すようにします。
   184  // これにより、長寿命の [FileSet] のメモリ使用量が減少し、無制限のファイルストリームに遭遇した場合でも処理が可能になります。
   185  //
   186  // セットに属さないファイルを削除しても効果はありません。
   187  func (s *FileSet) RemoveFile(file *File)
   188  
   189  // ファイルセット内のファイルを追加された順にfに呼び出し、fがfalseを返すまで繰り返します。
   190  func (s *FileSet) Iterate(f func(*File) bool)
   191  
   192  // File関数は、位置pを含むファイルを返します。
   193  // 該当するファイルが見つからない場合(たとえばp == [NoPos] の場合)、結果はnilです。
   194  func (s *FileSet) File(p Pos) (f *File)
   195  
   196  // PositionForは、ファイルセット内の [Pos] pを [Position] 値に変換します。
   197  // adjustedが設定されている場合、位置は位置変更を行うコメントによって調整される可能性があります。
   198  // そうでなければ、そのコメントは無視されます。
   199  // pはsまたは [NoPos] の [Pos] 値でなければなりません。
   200  func (s *FileSet) PositionFor(p Pos, adjusted bool) (pos Position)
   201  
   202  // Positionはファイルセット内の [Pos] pをPosition値に変換します。
   203  // s.Position(p)を呼び出すことは、s.PositionFor(p, true)を呼び出すことと同じです。
   204  func (s *FileSet) Position(p Pos) (pos Position)