lib/cukedep/feature-model.rb in cukedep-0.0.1 vs lib/cukedep/feature-model.rb in cukedep-0.0.3

- old
+ new

@@ -14,11 +14,13 @@ # See also: Is this topological sort in Ruby flawed? class FeatureModel FeatureDependencies = Struct.new(:dependee, :dependents) - +# Helper class used internally by FeatureModel class. +# Purpose: to try to create a valid dependency graph and perform a +# topological sort of the nodes. class DepGraph include TSort # Mix-in module for topological sorting attr_reader(:dependencies) @@ -59,11 +61,11 @@ end # Retrieve the feature file matching the given feature identifiers # theIds one or more Strings, each being one feature identifier def select_by_ids(*theIds) - features_by_ids = id2features() + features_by_ids = id2features selection = theIds.each_with_object([]) do |an_id, sub_result| found_feature = features_by_ids[an_id] if found_feature.nil? fail(StandardError, "No feature file with identifier '#{an_id}'.") end @@ -80,11 +82,11 @@ # Build an array of FileDependencies objects. def dependency_links() if @dependencies.nil? # Build the mapping: feature identifier => feature - features_by_id = id2features() + features_by_id = id2features # Resolve the dependency tags resolve_dependencies(features_by_id) end @@ -92,13 +94,13 @@ end # Sort the feature files by dependency order. def sort_features_by_dep() - dep_links = dependency_links() + dep_links = dependency_links graph = DepGraph.new(dep_links) - sorted_deps = graph.tsort() + sorted_deps = graph.tsort all_sorted = sorted_deps.map(&:dependee) @sorted_features = all_sorted.reject { |f| f.feature.anonymous? } end @@ -140,11 +142,11 @@ end def emit_heading(anIO) dir = File.dirname(File.absolute_path(feature_files[0].filepath)) - heading =<<-EOS + heading = <<-EOS // Graph of dependencies of feature files in directory: // '#{dir}' // This file uses the DOT syntax, a free utility from the Graphviz toolset. // Graphviz is available at: www.graphviz.org // File generated on #{Time.now.asctime}. @@ -164,39 +166,48 @@ def emit_body(anIO) anIO.puts <<-EOS subgraph island { node [shape = box, style=filled, color=lightgray]; EOS - feature_files.each_with_index { |ff, i| draw_node(anIO, ff, i) if ff.feature.anonymous? } + feature_files.each_with_index do |ff, i| + draw_node(anIO, ff, i) if ff.feature.anonymous? + end anIO.puts <<-EOS label = "Isolated features"; } subgraph dependencies { node [shape = box, fillcolor = none]; EOS - feature_files.each_with_index { |ff, i| draw_node(anIO, ff, i) unless ff.feature.anonymous? } + feature_files.each_with_index do |ff, i| + draw_node(anIO, ff, i) unless ff.feature.anonymous? + end anIO.puts <<-EOS label = "Dependencies"; } // The edges represent dependencies EOS - dependencies.each {|a_dep| draw_edge(anIO, a_dep) } + dependencies.each { |a_dep| draw_edge(anIO, a_dep) } end # Output the closing part of the graph drawing def emit_trailing(anIO) - anIO.puts "} // End of graph" + anIO.puts '} // End of graph' end # Draw a refinement node in DOT format def draw_node(anIO, aFeatureFile, anIndex) basename = File.basename(aFeatureFile.filepath, '.feature') - identifier_suffix = aFeatureFile.feature.anonymous? ? '' : " -- #{aFeatureFile.feature.identifier}" - anIO.puts %Q| node_#{anIndex} [label = "#{basename}#{identifier_suffix}"];| + its_feature = aFeatureFile.feature + if its_feature.anonymous? + id_suffix = '' + else + id_suffix = " -- #{its_feature.identifier}" + end + anIO.puts %Q| node_#{anIndex} [label = "#{basename}#{id_suffix}"];| end # Draw an edge between feature files having dependencies. def draw_edge(anIO, aDependency) source_id = feature_files.find_index(aDependency.dependee) @@ -210,22 +221,22 @@ end def generate_rake_tasks(rakefile, theProjDir) puts " #{rakefile}" - template_filepath = Pathname.new(File.dirname(__FILE__)).parent.parent + './templates/rake.erb' - template_source = File.read(template_filepath) + grandparent_path = Pathname.new(File.dirname(__FILE__)).parent.parent + template_source = File.read(grandparent_path + './templates/rake.erb') # Create one template engine instance engine = ERB.new(template_source) - source_dir = File.absolute_path(Dir.getwd()) + source_dir = File.absolute_path(Dir.getwd) proj_dir = File.absolute_path(theProjDir) - anonymous = anonymous_features.map {|ff| ff.basename} + anonymous = anonymous_features.map { |ff| ff.basename } feature_ids = feature_files.map { |ff| ff.feature.identifier } feature_ids.compact! - deps = dependencies.reject {|dep| dep.dependee.feature.anonymous?} + deps = dependencies.reject { |dep| dep.dependee.feature.anonymous? } # Generate the text representation with given context file_source = engine.result(binding) File.open(rakefile, 'w') { |f| f.write(file_source) } end @@ -264,11 +275,12 @@ end # Complain when dependency tag refers to an unknown feature dependents = dep_tags.map do |a_tag| unless aMapping.include?(a_tag) - msg = "Feature with identifier '#{its_id}' depends on unknown feature '#{a_tag}'" - fail(StandardError, msg) + msg_p1 = "Feature with identifier '#{its_id}'" + msg_p2 = " depends on unknown feature '#{a_tag}'" + fail(StandardError, msg_p1 = msg_p2) end aMapping[a_tag] end @dependencies << FeatureDependencies.new(feature_file, dependents)