Class: Glslkit::SourceMap

Inherits:
Object
  • Object
show all
Defined in:
lib/glslkit/source_map.rb

Overview

出力される #line <n> <index> ディレクティブで使われるファイル インデックスを、各インデックスが指すcanonical_pathに逆引きする。

あわせて「平坦化後の出力行 → (元ファイル, 元の行)」の区間マッピングを 保持する(§8.1)。テキスト上の#lineディレクティブはこのマッピングを 人間/GLSLコンパイラ向けに描画したものに過ぎず、line_directives: false で抑止されていてもこちらは常に記録される。

Defined Under Namespace

Classes: UnsupportedVersionError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSourceMap

Returns a new instance of SourceMap.



33
34
35
36
37
# File 'lib/glslkit/source_map.rb', line 33

def initialize
  @files = []
  @index_by_path = {}
  @segments = []
end

Instance Attribute Details

#filesObject (readonly)

Returns the value of attribute files.



39
40
41
# File 'lib/glslkit/source_map.rb', line 39

def files
  @files
end

Class Method Details

.from_h(hash) ⇒ Object

spec/schema/source-map-v1.json に対応するHashから復元する(M8g)。 segmentsoutput_line 昇順であることを前提にする(to_h は 常にソート済みで出力する)。ソートされていない入力を渡した場合の resolve の結果は未定義— 呼び出し側で保証すること。



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/glslkit/source_map.rb', line 21

def self.from_h(hash)
  version = hash.fetch("version")
  raise UnsupportedVersionError, "unsupported source map version: #{version.inspect}" unless version == 1

  source_map = new
  hash.fetch("files").each { |path| source_map.index_for(path) }
  hash.fetch("segments").each do |output_line, file_index, source_line|
    source_map.add_segment(output_line: output_line, file_index: file_index, source_line: source_line)
  end
  source_map
end

Instance Method Details

#add_segment(output_line:, file_index:, source_line:) ⇒ Object

output_line以降、次のadd_segment呼び出しまで(または出力の終わりまで)は file_indexのファイルのsource_line以降に1対1で対応する、という区間を 登録する。呼び出し順はoutput_line昇順であること(Preprocessorはこの順で 呼ぶ)。



63
64
65
# File 'lib/glslkit/source_map.rb', line 63

def add_segment(output_line:, file_index:, source_line:)
  @segments << Segment.new(output_line, file_index, source_line)
end

#index_for(path) ⇒ Object



52
53
54
55
56
57
# File 'lib/glslkit/source_map.rb', line 52

def index_for(path)
  @index_by_path[path] ||= begin
    @files << path
    @files.size - 1
  end
end

#resolve(output_line) ⇒ Object

output_lineが属する区間を二分探索し、[canonical_path, source_line]を 返す。どの区間にも属さない(記録前の行、または区間が1つも無い)場合はnil。



69
70
71
72
73
74
# File 'lib/glslkit/source_map.rb', line 69

def resolve(output_line)
  segment = segment_for(output_line)
  return nil unless segment

  [@files[segment.file_index], segment.source_line + (output_line - segment.output_line)]
end

#to_hObject

spec/schema/source-map-v1.json に対応するHashを返す。segments は 呼び出し順(=Preprocessorがoutput_line昇順で呼ぶ順)を信頼せず、 明示的に output_line 昇順にソートしてから出力する。



44
45
46
47
48
49
50
# File 'lib/glslkit/source_map.rb', line 44

def to_h
  {
    "version" => 1,
    "files" => @files,
    "segments" => @segments.sort_by(&:output_line).map { |s| [s.output_line, s.file_index, s.source_line] }
  }
end