feddcbf2创建于 2025年2月13日历史提交
#!/usr/bin/env ruby
# Copyright (c) 2021-2025 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'ostruct'
require 'set'
require 'delegate'

module Keywords
  module_function

  def extensions
    @extensions
  end

  def keywords
    @keywords
  end

  def build_tree(keys)
    tree = Hash.new()
    offset = 0

    while true
      has_more = false
      keys.each do |key|
          if key.length < offset + 1
            next
          end

        has_more = true
        func_name = key[0..offset];
        if tree.has_key?(func_name)
          tree[func_name].add(key[offset + 1])
        else
          tree[func_name] = Set[key[offset + 1]]
        end
      end

      if has_more
        offset += 1
        next
      end
      break
    end

    return tree
  end

  def wrap_data(data)
    @extensions = Hash.new()

    if !data || !data.extensions || !data.keywords
      return
    end

    @keywords = data.keywords.map do |keyword|
      keyword.string = keyword.name
      keyword
    end

    data.extensions.each do |extension|
      @extensions[extension.name] = Hash.new()
      all_words = data.keywords.select do |desc|
        s_kw = Set.new(desc&.keyword)
        groups = [s_kw, Set.new(desc&.keyword_like), Set.new(desc&.custom_handler)]
        groups.combination(2).each { |a,b| raise "Conflicting keyword type" unless (a & b).empty? }

        active = Set.new();
        groups.each { |group| active.merge(group) }

        raise "Unknown extension" unless active.subset?(Set.new(data.extensions.map { |ext| ext.name }))
        active.include? extension.name
      end

      keywords = data.keywords.select do |desc|
        desc&.keyword&.include? extension.name or desc&.custom_handler&.include? extension.name
      end

      @extensions[extension.name]['keywords'] = keywords
      @extensions[extension.name]['keyword_starts'] = Set.new(keywords.map { |desc| desc.name[0] })
      @extensions[extension.name]['all_words'] = all_words
      @extensions[extension.name]['all_word_starts'] = Set.new(all_words.map { |desc| desc.name[0] })
      @extensions[extension.name]['tree'] = build_tree(all_words.map { |desc| desc.name })
    end
  end
end

def Gen.on_require(data)
  Keywords.wrap_data(data)
end