class MxxRu::Cpp::Analyzer::CppAnalyzer

Public Class Methods

new() click to toggle source
# File lib/mxx_ru/cpp/analyzer.rb, line 70
def initialize
  # Key is a string, value - SourceFile.
  @sources = Hash.new
  # A list of folders to look header files in.
  @include_paths = Array.new
end

Public Instance Methods

add_include_paths( a_paths ) click to toggle source

Add paths to header files.

a_paths

Should be Array of Strings.

# File lib/mxx_ru/cpp/analyzer.rb, line 90
def add_include_paths( a_paths )
  a_paths.each { |p|
      if !@include_paths.include?( p )
        @include_paths << p
      end
    }
end
add_sources( a_sources ) click to toggle source

Add files to view.

a_sources

Should be Array of Strings.

# File lib/mxx_ru/cpp/analyzer.rb, line 79
def add_sources( a_sources )

  a_sources.each { |s|
      if !@sources.key?( s )
        @sources[ s ] = SourceFile.new
      end
    }
end
analyze( a_encoding ) click to toggle source

Perform file analisys.

# File lib/mxx_ru/cpp/analyzer.rb, line 99
def analyze ( a_encoding )
  # Current list of keys should be taken to avoid
  # dynamic growth of file list.
  # Repeat iterations until source file list changes stop
  old_size = 0
  files = @sources.keys
  while old_size != files.size
    files.each { |file_name|
        current = @sources[ file_name ]
        if !current.is_processed
          process_file( file_name, current, a_encoding )
        end
      }

    old_size = files.size
    files = @sources.keys
  end
end
get_depends_for( a_file_name ) click to toggle source

Get full dependencies list for a file. Returns Array of Strings.

# File lib/mxx_ru/cpp/analyzer.rb, line 120
def get_depends_for( a_file_name )
  result_hash = Hash.new
  file_obj = @sources[ a_file_name ]
  if nil != file_obj
    to_review = file_obj.depends
    to_review_next = Hash.new

    while to_review.size != to_review_next.size
      to_review.each_key { |f|
          if !result_hash.key?( f )
            result_hash[ f ] = nil
            to_review_next_obj = @sources[ f ]
            to_review_next_obj.depends.each_key { |k|
                to_review_next[ k ] = nil }
          end
        }

      to_review = to_review_next
      to_review_next = Hash.new
    end
  end

  return result_hash.keys
end

Protected Instance Methods

add_depend_to( a_owner_obj, a_depend_name ) click to toggle source

Add dependency to a file.

a_owner_obj

Dependency owner.

a_depend_name

Dependency file name.

# File lib/mxx_ru/cpp/analyzer.rb, line 223
def add_depend_to( a_owner_obj, a_depend_name )

  a_owner_obj << a_depend_name

  if !@sources.key?( a_depend_name )
    # This file wasn't viewed yet.
    @sources[ a_depend_name ] = SourceFile.new
  end
end
process_file( a_file_name, a_file_obj, a_encoding ) click to toggle source

Process next file.

a_file_name

File name.

a_file_obj

Corresponding object.

# File lib/mxx_ru/cpp/analyzer.rb, line 149
def process_file( a_file_name, a_file_obj, a_encoding )

  # Gather file names list from include directives.
  std_path_included = Array.new
  local_path_included = Array.new
  IO.foreach( a_file_name , encoding: "#{a_encoding}" ) { |line|
      r = @@include_regex.match( line )
      if nil != r
        if "<" == r[ 1 ]
          std_path_included << r[ 2 ]
        else
          local_path_included << r[ 2 ]
        end
      end
    }

  # All files, loaded through include <>
  # should be searched in standard search paths only.
  std_path_included.each { |f|
      process_std_include_path_file( f, a_file_obj )
    }

  if local_path_included.size
    # Files loaded through include ""
    # should be searched in folder with the source file first.
    local_path = File.dirname( a_file_name )
    local_path_included.each { |f|
        process_local_include_path_file( f, local_path, a_file_obj )
      }
  end

  a_file_obj.processed
end
process_local_include_path_file( a_file_name, a_local_path, a_owner_obj ) click to toggle source

Processing file loaded through include “”

a_file_name

File name.

a_local_path

Folder with owner_obj.

a_owner_obj

File object contained include directive.

# File lib/mxx_ru/cpp/analyzer.rb, line 202
def process_local_include_path_file(
  a_file_name,
  a_local_path,
  a_owner_obj )

  test_name = # This trick is necessary to handle relative includes
              # like ../details/some_header.h.
              # Without calling cleanpath there could be created many
              # names in form local/path/details/../details/../details
    Pathname.new(
      File.join( a_local_path, a_file_name ) ).cleanpath
  if File.exists?( test_name )
    add_depend_to( a_owner_obj, test_name )
  else
    process_std_include_path_file( a_file_name, a_owner_obj )
  end
end
process_std_include_path_file( a_file_name, a_owner_obj ) click to toggle source

Processing file loaded through include <>

a_file_name

File name.

a_owner_obj

File object contained include directive.

# File lib/mxx_ru/cpp/analyzer.rb, line 186
def process_std_include_path_file( a_file_name, a_owner_obj )
  @include_paths.find { |path|
      test_name = File.join( [ path, a_file_name ] )
      if File.exists?( test_name )
        add_depend_to( a_owner_obj, test_name )
        true
      else
        false
      end
    }
end