tool-shed 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. data/Gemfile +9 -0
  2. data/LICENSE +20 -0
  3. data/README.md +52 -0
  4. data/bin/as-asset-detector +16 -0
  5. data/bin/as-class-detector +16 -0
  6. data/bin/as-docp +16 -0
  7. data/bin/as-manifest +16 -0
  8. data/bin/as-style-detector +16 -0
  9. data/coverage/unit/index.html +330 -0
  10. data/coverage/unit/jquery-1.3.2.min.js +19 -0
  11. data/coverage/unit/jquery.tablesorter.min.js +15 -0
  12. data/coverage/unit/lib-hel-asdoc_package_rb.html +447 -0
  13. data/coverage/unit/lib-hel-manifest_rb.html +555 -0
  14. data/coverage/unit/lib-hel-opts-asdoc_package_opts_rb.html +195 -0
  15. data/coverage/unit/lib-hel-opts-manifest_opts_rb.html +195 -0
  16. data/coverage/unit/lib-hel-opts-tool_opts_rb.html +531 -0
  17. data/coverage/unit/lib-hel-opts-unused_class_opts_rb.html +207 -0
  18. data/coverage/unit/lib-hel-opts-unused_style_opts_rb.html +201 -0
  19. data/coverage/unit/lib-hel-project_tools_rb.html +423 -0
  20. data/coverage/unit/lib-hel-search_rb.html +363 -0
  21. data/coverage/unit/lib-hel-stripper_rb.html +357 -0
  22. data/coverage/unit/lib-hel-tool_rb.html +423 -0
  23. data/coverage/unit/lib-hel-unused_class_rb.html +675 -0
  24. data/coverage/unit/lib-hel-unused_style_rb.html +747 -0
  25. data/coverage/unit/lib-hel-version_rb.html +135 -0
  26. data/coverage/unit/lib-hel_tools_rb.html +165 -0
  27. data/coverage/unit/print.css +12 -0
  28. data/coverage/unit/rcov.js +42 -0
  29. data/coverage/unit/screen.css +270 -0
  30. data/coverage.data +0 -0
  31. data/lib/shed/asdoc_package.rb +64 -0
  32. data/lib/shed/manifest.rb +82 -0
  33. data/lib/shed/opts/asdoc_package_opts.rb +22 -0
  34. data/lib/shed/opts/manifest_opts.rb +22 -0
  35. data/lib/shed/opts/tool_opts.rb +114 -0
  36. data/lib/shed/opts/unused_asset_opts.rb +24 -0
  37. data/lib/shed/opts/unused_class_opts.rb +24 -0
  38. data/lib/shed/opts/unused_style_opts.rb +23 -0
  39. data/lib/shed/project_tools.rb +60 -0
  40. data/lib/shed/search.rb +50 -0
  41. data/lib/shed/stripper.rb +49 -0
  42. data/lib/shed/tool.rb +60 -0
  43. data/lib/shed/unused_asset.rb +68 -0
  44. data/lib/shed/unused_class.rb +102 -0
  45. data/lib/shed/unused_style.rb +114 -0
  46. data/lib/shed/version.rb +12 -0
  47. data/lib/tool_shed.rb +19 -0
  48. data/rakefile.rb +109 -0
  49. data/rdoc/classes/ASDocPackage.html +281 -0
  50. data/rdoc/classes/ASDocPackageOpts.html +204 -0
  51. data/rdoc/classes/Manifest.html +323 -0
  52. data/rdoc/classes/ManifestOpts.html +205 -0
  53. data/rdoc/classes/ProjectTools.html +302 -0
  54. data/rdoc/classes/Search.html +203 -0
  55. data/rdoc/classes/Stripper.html +223 -0
  56. data/rdoc/classes/Tool.html +313 -0
  57. data/rdoc/classes/ToolOpts.html +297 -0
  58. data/rdoc/classes/UnusedClass.html +258 -0
  59. data/rdoc/classes/UnusedClassOpts.html +206 -0
  60. data/rdoc/classes/UnusedStyle.html +277 -0
  61. data/rdoc/classes/UnusedStyleOpts.html +205 -0
  62. data/rdoc/created.rid +1 -0
  63. data/rdoc/files/LICENSE.html +129 -0
  64. data/rdoc/files/README_md.html +138 -0
  65. data/rdoc/files/lib/hel/asdoc_package_rb.html +107 -0
  66. data/rdoc/files/lib/hel/manifest_rb.html +107 -0
  67. data/rdoc/files/lib/hel/opts/asdoc_package_opts_rb.html +107 -0
  68. data/rdoc/files/lib/hel/opts/manifest_opts_rb.html +107 -0
  69. data/rdoc/files/lib/hel/opts/tool_opts_rb.html +114 -0
  70. data/rdoc/files/lib/hel/opts/unused_class_opts_rb.html +107 -0
  71. data/rdoc/files/lib/hel/opts/unused_style_opts_rb.html +107 -0
  72. data/rdoc/files/lib/hel/project_tools_rb.html +107 -0
  73. data/rdoc/files/lib/hel/search_rb.html +114 -0
  74. data/rdoc/files/lib/hel/stripper_rb.html +107 -0
  75. data/rdoc/files/lib/hel/tool_rb.html +107 -0
  76. data/rdoc/files/lib/hel/unused_class_rb.html +107 -0
  77. data/rdoc/files/lib/hel/unused_style_rb.html +107 -0
  78. data/rdoc/files/lib/hel/version_rb.html +107 -0
  79. data/rdoc/files/lib/hel_tools_rb.html +127 -0
  80. data/rdoc/fr_class_index.html +39 -0
  81. data/rdoc/fr_file_index.html +43 -0
  82. data/rdoc/fr_method_index.html +75 -0
  83. data/rdoc/index.html +24 -0
  84. data/rdoc/rdoc-style.css +208 -0
  85. data/test/fixtures/search/App.mxml +0 -0
  86. data/test/fixtures/search/hide/Hidden.as +0 -0
  87. data/test/fixtures/search/org/helvector/Main.as +0 -0
  88. data/test/fixtures/src/org/helvector/Helvector.as +16 -0
  89. data/test/fixtures/src/org/helvector/one/HelOne.as +14 -0
  90. data/test/fixtures/src/org/helvector/one/HelOneTwo.mxml +0 -0
  91. data/test/fixtures/src/org/helvector/one/package.asdoc +1 -0
  92. data/test/fixtures/src/org/helvector/package.asdoc +1 -0
  93. data/test/fixtures/src/org/helvector/three/HelThree.as +14 -0
  94. data/test/fixtures/src/org/helvector/three/package.asdoc +1 -0
  95. data/test/fixtures/src/org/helvector/two/HelTwo.as +14 -0
  96. data/test/fixtures/src/org/helvector/two/package.asdoc +1 -0
  97. data/test/fixtures/unused-asset/assets/css/referenced.css +0 -0
  98. data/test/fixtures/unused-asset/assets/css/un-referenced.css +0 -0
  99. data/test/fixtures/unused-asset/assets/fonts/referenced.otf +0 -0
  100. data/test/fixtures/unused-asset/assets/fonts/un-referenced.otf +0 -0
  101. data/test/fixtures/unused-asset/assets/img/referenced.jpg +0 -0
  102. data/test/fixtures/unused-asset/assets/img/referenced.png +0 -0
  103. data/test/fixtures/unused-asset/assets/img/un-referenced.jpg +0 -0
  104. data/test/fixtures/unused-asset/assets/img/un-referenced.png +0 -0
  105. data/test/fixtures/unused-asset/src/org/helvector/ToolShed.as +30 -0
  106. data/test/fixtures/unused-cla/link-report.xml +17 -0
  107. data/test/fixtures/unused-cla/manifest.xml +6 -0
  108. data/test/fixtures/unused-cla/src/Unused.as +0 -0
  109. data/test/fixtures/unused-cla/src/Used.as +0 -0
  110. data/test/fixtures/unused-css/css/styles.css +2 -0
  111. data/test/fixtures/unused-css/css-multiple/more.css +2 -0
  112. data/test/fixtures/unused-css/css-multiple/styles.css +2 -0
  113. data/test/fixtures/unused-css/css-with-comments/commented.css +6 -0
  114. data/test/fixtures/unused-css/src/CSSApp.mxml +5 -0
  115. data/test/test_helper.rb +9 -0
  116. data/test/unit/test_asdoc_package.rb +72 -0
  117. data/test/unit/test_asdoc_package_opts.rb +28 -0
  118. data/test/unit/test_manifest.rb +53 -0
  119. data/test/unit/test_manifest_opts.rb +28 -0
  120. data/test/unit/test_search.rb +67 -0
  121. data/test/unit/test_source_tools.rb +97 -0
  122. data/test/unit/test_stripper.rb +56 -0
  123. data/test/unit/test_tool.rb +73 -0
  124. data/test/unit/test_tool_opts.rb +81 -0
  125. data/test/unit/test_unused_asset.rb +59 -0
  126. data/test/unit/test_unused_asset_opts.rb +32 -0
  127. data/test/unit/test_unused_class.rb +50 -0
  128. data/test/unit/test_unused_class_opts.rb +32 -0
  129. data/test/unit/test_unused_style.rb +103 -0
  130. data/test/unit/test_unused_style_opts.rb +31 -0
  131. data/tool-shed-0.0.3.gem +0 -0
  132. data/tool-shed.gemspec +41 -0
  133. metadata +265 -0
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Scans a specified source tree for ActionScript and MXML files and for each one
5
+ # found creates a manifest entry. When complete writes the resulting manfiest
6
+ # file to disk.
7
+ #
8
+ class Manifest < Tool
9
+ attr_reader :components,
10
+ :xml
11
+
12
+ def initialize(opt,out=STDOUT)
13
+ super(opt,out)
14
+
15
+ @filetypes = /\.(as|mxml)$/
16
+
17
+ build
18
+ end
19
+
20
+ #
21
+ # Generates a hash containing id and xml vales. The xml can be to be inserted
22
+ # into the manifest for the specified class.
23
+ #
24
+ def add(path, id)
25
+ log("Adding '#{path}'")
26
+
27
+ cp = ProjectTools.import(path)
28
+
29
+ { :key => id, :xml => "<component id=\"#{id}\" class=\"#{cp}\" />" }
30
+ end
31
+
32
+ #
33
+ # Search the provided path for as and mxml documents and return those found as
34
+ # a list.
35
+ #
36
+ def scan(path)
37
+ puts "Scanning '#{path}' for as and mxml files..."
38
+
39
+ found = []
40
+
41
+ Search.find_all(@filetypes,path,@excludes) do |p|
42
+ ext = File.extname(p)
43
+ cn = File.basename(p, ext)
44
+
45
+ found << add(p, cn) if cn =~ /^[A-Z]/
46
+ end
47
+
48
+ found.uniq! unless found.empty?
49
+
50
+ found
51
+ end
52
+
53
+ #
54
+ # Build the manifest file and save it to disk.
55
+ #
56
+ def build
57
+ @components = scan(@src)
58
+
59
+ if @components.empty?
60
+ puts "No ActionScript or Mxml files found."
61
+ else
62
+
63
+ @components.sort! {|a,b| a[:xml] <=> b[:xml] }
64
+
65
+ @xml = create_xml(@components)
66
+
67
+ #Open/Create the manifest file and write the output to it.
68
+ to_disk(@xml)
69
+ end
70
+ end
71
+
72
+ #
73
+ # Constructs the flex complier config file when given a list of paths to asdoc
74
+ # files.
75
+ #
76
+ def create_xml(comps)
77
+ x = "<?xml version='1.0'?>\n<componentPackage>\n"
78
+ comps.each { |c| x << "\t#{c[:xml]}\n" }
79
+ x << "</componentPackage>"
80
+ x
81
+ end
82
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Manages the command line interface for the ASDoc Package File tool.
5
+ #
6
+ class ASDocPackageOpts < ToolOpts
7
+
8
+ def self.name
9
+ 'as-docp'
10
+ end
11
+
12
+ def self.description
13
+ 'ASDoc Package Builder'
14
+ end
15
+
16
+ def self.default_config
17
+ dc = superclass.default_config
18
+ dc[:output] = 'package-asdoc.xml'
19
+ dc
20
+ end
21
+
22
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Manages the command line interface for the AS3 Manifest File generation tool.
5
+ #
6
+ class ManifestOpts < ToolOpts
7
+
8
+ def self.description
9
+ "ActionScript Manifest Generator Tool"
10
+ end
11
+
12
+ def self.name
13
+ "as-manifest"
14
+ end
15
+
16
+ def self.default_config
17
+ dc = superclass.default_config
18
+ dc[:output] = "manifest.xml"
19
+ dc
20
+ end
21
+
22
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+
3
+ require 'optparse'
4
+
5
+ #
6
+ # Abstract layer for the tool shed options parsers. This sets the basic
7
+ # paramaters the tools respond to via the command line.
8
+ #
9
+ class ToolOpts
10
+
11
+ #
12
+ # The name of the tool, as invoked on the command line.
13
+ #
14
+ def self.name
15
+ ToolShed::NAME
16
+ end
17
+
18
+ #
19
+ # A basic description of the tools use.
20
+ #
21
+ def self.description
22
+ 'Tool'
23
+ end
24
+
25
+ #
26
+ # A version string to describe the version of the tool these options are
27
+ # designed to invoke.
28
+ #
29
+ def self.version
30
+ ToolShed::VERSION::STRING
31
+ end
32
+
33
+ #
34
+ # Default configuration hash.
35
+ #
36
+ def self.default_config
37
+ {
38
+ :src => ".",
39
+ :output => 'output.xml',
40
+ :verbose => false,
41
+ :silent => false
42
+ }
43
+ end
44
+
45
+ #
46
+ # Create and return the options parser with the default header.
47
+ #
48
+ def self.create_parser
49
+ op = OptionParser.new
50
+ op.banner = "Usage: #{name} [options]"
51
+
52
+ op.separator ""
53
+ op.separator "Options:"
54
+ op
55
+ end
56
+
57
+ #
58
+ # Add all mandatory arguments to the options parser.
59
+ #
60
+ def self.add_mandatory(op,config)
61
+ end
62
+
63
+ #
64
+ # Add all optional arguments to the options parser.
65
+ #
66
+ def self.add_optional(op,config)
67
+ op.on("-s", "--source [PATH]", String, "Path to source folder, defaults to current directory.") do |v|
68
+ config[:src] = v
69
+ end
70
+
71
+ op.on("-o", "--output [FILE PATH]", String, "Path to output file, defaults to #{config[:output]}") do |v|
72
+ config[:output] = v
73
+ end
74
+
75
+ op.on("-v", "--verbose", "Run verbosely") do |v|
76
+ config[:verbose] = v
77
+ end
78
+
79
+ op.on("--silent", "Supress all output.") do |v|
80
+ config[:silent] = v
81
+ end
82
+ end
83
+
84
+ def self.add_tail(op,out)
85
+ op.on_tail("-h", "--help", "Show this help message") do
86
+ out.puts op
87
+ exit
88
+ end
89
+
90
+ op.on_tail("--version", "Show version") do
91
+ out.puts "#{description} version #{version}"
92
+ exit
93
+ end
94
+ end
95
+
96
+ #
97
+ # Parse the arugments and return a config hash.
98
+ #
99
+ def self.parse(args,out=STDOUT)
100
+
101
+ config = default_config()
102
+ options = create_parser()
103
+
104
+ add_mandatory(options,config)
105
+ add_optional(options,config)
106
+
107
+ add_tail(options,out)
108
+
109
+ options.parse!(args)
110
+
111
+ config
112
+ end
113
+
114
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Manages the command line interface for the unused assets detection tool.
5
+ #
6
+ class UnusedAssetOpts < ToolOpts
7
+
8
+ def self.name
9
+ "as-asset-detector"
10
+ end
11
+
12
+ def self.description
13
+ " ActionScript Unused Asset Detection Tool"
14
+ end
15
+
16
+ def self.default_config
17
+ dc = superclass.default_config
18
+ dc[:output] = 'assets.txt'
19
+ dc[:manifest] = 'manifest.xml'
20
+ dc[:link_report] = 'link-report.xml'
21
+ dc
22
+ end
23
+
24
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Manages the command line interface for the unused classes detection tool.
5
+ #
6
+ class UnusedClassOpts < ToolOpts
7
+
8
+ def self.name
9
+ "as-class-detector"
10
+ end
11
+
12
+ def self.description
13
+ "ActionScript unused class detection tool"
14
+ end
15
+
16
+ def self.default_config
17
+ dc = superclass.default_config
18
+ dc[:output] = 'classes.txt'
19
+ dc[:manifest] = 'manifest.xml'
20
+ dc[:link_report] = 'link-report.xml'
21
+ dc
22
+ end
23
+
24
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Manages the command line interface for the unused style detection tool.
5
+ #
6
+ class UnusedStyleOpts < ToolOpts
7
+
8
+ def self.name
9
+ "as-style-detector"
10
+ end
11
+
12
+ def self.description
13
+ " ActionScript Unused Style Detection Tool"
14
+ end
15
+
16
+ def self.default_config
17
+ dc = superclass.default_config
18
+ dc[:output] = 'styles.txt'
19
+ dc[:css_dir] = 'style'
20
+ dc
21
+ end
22
+
23
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # A collection of utility methods to help working with ActionScript source.
5
+ #
6
+ class ProjectTools
7
+
8
+ #
9
+ # Returns an array of directory names that are commonly used
10
+ # as the root directory for source files.
11
+ #
12
+ def self.common_src_dirs
13
+ ['src','source','test','lib']
14
+ end
15
+
16
+ #
17
+ # Takes a file path and truncates it to the last matching conventionally named
18
+ # source directory.
19
+ #
20
+ def self.truncate_to_src(path)
21
+ common_src_dirs.each do |remove|
22
+ path = path.gsub(/^.*\b#{remove}\b(\/|$)/, '');
23
+ end
24
+ path
25
+ end
26
+
27
+ #
28
+ # Removes any relative prefixes found in the provided path.
29
+ #
30
+ def self.remove_relative_prefix(path)
31
+ path.sub(/^\W+\b/, '')
32
+ end
33
+
34
+ #
35
+ # Takes a file path and converts it to a package path using conventionally
36
+ # named source folders as the root marker.
37
+ #
38
+ def self.package(path)
39
+ path = remove_relative_prefix(path)
40
+ path = File.dirname(path) if path =~ flex_file_regx
41
+ truncate_to_src(path).gsub('/','.')
42
+ end
43
+
44
+ #
45
+ # Takes a file path and converts it to a import path using conventionally
46
+ # named source folders as the root marker.
47
+ #
48
+ def self.import(path)
49
+ truncate_to_src(path).gsub('/','.').sub(flex_file_regx,'')
50
+ end
51
+
52
+ #
53
+ # Regular expression to match files we expect to find in a ActionScript/Flex
54
+ # project.
55
+ #
56
+ def self.flex_file_regx
57
+ /\.(as|mxml|asdoc)$/
58
+ end
59
+
60
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Collection of methods for searching directories.
5
+ #
6
+ module Search
7
+
8
+ require 'find'
9
+
10
+ #
11
+ # Searches a directory and it's child directories for all the files whose
12
+ # names match the specified regular expression.
13
+ #
14
+ def self.find_all(files_of_type,dir,excluding=[])
15
+
16
+ Find.find(dir) do |path|
17
+ if FileTest.directory?(path)
18
+
19
+ if excluding.include?(File.basename(path))
20
+ Find.prune
21
+ else
22
+ next
23
+ end
24
+
25
+ elsif File.extname(path) =~ files_of_type
26
+ yield path
27
+ end
28
+ end
29
+ end
30
+
31
+ #
32
+ # Scans the path and its children for empty directories.
33
+ #
34
+ def self.for_empties(path,excluding=[])
35
+
36
+ Find.find(path) do |p|
37
+
38
+ if FileTest.directory?(p)
39
+ if excluding.include?(File.basename(p))
40
+ Find.prune
41
+ else
42
+ # Any dir that only contains ., .., and .svn or .git are empty.
43
+ yield p if Dir.entries(p).join =~ /^\.\.\.(\.(svn|git))?$/
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ module Stripper
4
+
5
+ class << self
6
+
7
+ #
8
+ # Strips xml comments from the document.
9
+ #
10
+ def xml_comments(str)
11
+ str.gsub!(/<!--(?:.|([\r\n]))*?-->/,'')
12
+ str.gsub(/<!--.*-->/,'')
13
+ str
14
+ end
15
+
16
+ #
17
+ # Strips comments from the document.
18
+ #
19
+ def ecma_comments(str)
20
+
21
+ str.gsub!(/\/\*(?:.|([\r\n]))*?\*\//,'')
22
+
23
+ # This is designed to leave whitespace in
24
+ # place so the caret position remains correct.
25
+ #do |s|
26
+ # if $1
27
+ # a = s.split("\n")
28
+ # r = "\n" * (a.length-1) if a.length > 1
29
+ # r
30
+ # end
31
+ #end
32
+
33
+ str.gsub!(/\/\/.*$/,'')
34
+ str
35
+
36
+ end
37
+
38
+ #
39
+ # Strips both xml and ecma script comments.
40
+ #
41
+ def comments(str)
42
+ str = xml_comments(str)
43
+ str = ecma_comments(str)
44
+ str
45
+ end
46
+
47
+ end
48
+
49
+ end
data/lib/shed/tool.rb ADDED
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # Abstract base class for tools. Provides basic default settings, and allows
5
+ # control over the level of logging to standard out.
6
+ #
7
+ class Tool
8
+
9
+ INVALID_OPTS = "Warning Invalid Options."
10
+
11
+ def initialize(opt,out=STDOUT)
12
+ @src = opt[:src] || '.'
13
+ @output = opt[:output] || 'tool-shed.txt'
14
+ @verbose = opt[:verbose] || false
15
+ @silent = opt[:silent] || false
16
+ @excludes = opt[:excludes] || ['.svn','.git']
17
+ @out = out
18
+ end
19
+
20
+ #
21
+ # Puts the message unless we are in silent mode.
22
+ #
23
+ def puts(msg)
24
+ @out.puts msg unless @silent
25
+ end
26
+
27
+ #
28
+ # Puts the message if we are in verbose mode (but not in silent mode).
29
+ #
30
+ def log(msg)
31
+ puts msg if @verbose
32
+ end
33
+
34
+ #
35
+ # Validates the opts the tool has been invoked with.
36
+ #
37
+ def valid_opts
38
+ true
39
+ end
40
+
41
+ #
42
+ # Write the requested string to the output file.
43
+ #
44
+ def to_disk(str)
45
+ f = File.open(@output, "w")
46
+ f.puts str
47
+ f.flush
48
+ f.close
49
+
50
+ puts "Saved result to #{File.expand_path(@output)}."
51
+ end
52
+
53
+ #
54
+ # Generate a timestamp to include in reports.
55
+ #
56
+ def generated_at
57
+ "Generated at" + Time.now.strftime(" [%m/%d/%Y %H:%M:%S] ")
58
+ end
59
+
60
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # This script scans all Actionscript classes and CSS files in a project to
5
+ # identify assets, like PNG files, that are in the project source tree but are
6
+ # no longer used by the application.
7
+ #
8
+ class UnusedAsset < Tool
9
+ def initialize(opt,out=STDOUT)
10
+ super(opt,out)
11
+
12
+ @link_report = opt[:link_report]
13
+ @manifest = opt[:manifest]
14
+
15
+ unless valid_opts
16
+ @out.puts "#{INVALID_OPTS} One or all of specified link report, manifest file, and source directories does not exist."
17
+ return
18
+ end
19
+
20
+ @declared_regex = /^TODO/
21
+
22
+ detect
23
+
24
+ @report = describe
25
+
26
+ to_disk(@report)
27
+ end
28
+
29
+ def valid_opts
30
+ File.exist?(@link_report) && File.exist?(@manifest) && File.exist?(@src) rescue false
31
+ end
32
+
33
+ def detect
34
+ @declared = scan_dirs(/\.(css|as|mxml)/, @src, @declared_regex)
35
+ end
36
+
37
+ private
38
+
39
+ #
40
+ # Scans directories for all files that match the file extension regex, and
41
+ # for each match goes on to scan that document for items matching the syntax
42
+ # regex.
43
+ #
44
+ def scan_dirs(extension_regex,path,syntax_regex)
45
+ d = []
46
+
47
+ Search.find_all(extension_regex,path,@excludes) do |path|
48
+ d << scan_doc(path,syntax_regex)
49
+ end
50
+
51
+ d.flatten!.sort!.uniq! unless d.empty?
52
+ d
53
+ end
54
+
55
+ #
56
+ # Opens the document specified by path and returns a list of all first capture
57
+ # group matches, after stripping comments.
58
+ #
59
+ def scan_doc(path,regex)
60
+ n = []
61
+ f = File.open(path,"r").read.strip
62
+ f = Stripper.comments(f)
63
+ f.scan(regex) do |style_name|
64
+ n << $1
65
+ end
66
+ n
67
+ end
68
+ end
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # This tool compares a mxmlc generated link-report against a manifest file
5
+ # created by the as-manifest tool to identify files that are in the project
6
+ # source tree but are no longer used by the application.
7
+ #
8
+ # Before executing this script make sure the relevant link reports and manifest
9
+ # files have been generated.
10
+ #
11
+ class UnusedClass < Tool
12
+ attr_reader :report,
13
+ :empty_packages,
14
+ :unused_classes
15
+
16
+ def initialize(opt,out=STDOUT)
17
+ super(opt,out)
18
+
19
+ @link_report = opt[:link_report]
20
+ @manifest = opt[:manifest]
21
+ @link_regex = /<script name=".*\/(\w+)\.(as|mxml)/
22
+ @manifest_regex = /<component id="(\w+)"/
23
+
24
+ unless valid_opts
25
+ @out.puts "#{INVALID_OPTS} One or all of the specified link report, manifest file, or source directory does not exist."
26
+ return
27
+ end
28
+
29
+ detect
30
+
31
+ @report = describe
32
+
33
+ to_disk(@report)
34
+ end
35
+
36
+ def valid_opts
37
+ File.exist?(@link_report) && File.exist?(@manifest) && File.exist?(@src) rescue false
38
+ end
39
+
40
+ def detect
41
+ puts "Scanning project for classes that are uncompiled..."
42
+
43
+ @manifest_classes = linked(@manifest, @manifest_regex, 'manifest')
44
+ @link_classes = linked(@link_report, @link_regex, 'link-report')
45
+
46
+ @unused_classes = @manifest_classes-@link_classes
47
+ @empty_packages = empties(@src)
48
+
49
+ puts "Unused classes: #{@unused_classes.length.to_s}"
50
+ puts "Empty packages: #{@empty_packages.length.to_s}"
51
+ end
52
+
53
+ private
54
+
55
+ #
56
+ # Scans the path for empty directories and lists them.
57
+ #
58
+ def empties(path)
59
+ e = []
60
+ Search.for_empties(path) { |p| e << p.sub( /^.*src\//, "") }
61
+ e
62
+ end
63
+
64
+ #
65
+ # Returns a string detailing the findings of the unused class detection.
66
+ #
67
+ def describe
68
+ d = generated_at
69
+ d << add_desc(" classes are in the manifest but not in the link report:", @unused_classes)
70
+ d << add_desc(" packages appear to be empty:", @empty_packages)
71
+ d
72
+ end
73
+
74
+ #
75
+ # Prints a description category.
76
+ #
77
+ def add_desc(txt,list)
78
+ l = list.empty? ? '' : list.join("\n")
79
+ "#{list.length} #{txt}\n#{l}"
80
+ end
81
+
82
+ #
83
+ # Collects all the lines in the specified link file matching the regular
84
+ # expression and returns them in a list.
85
+ #
86
+ def linked(link,rgx,desc)
87
+ log("Loading #{desc}: #{File.expand_path(link)}")
88
+
89
+ classes = []
90
+
91
+ return classes unless !link.nil? && File.exists?(link)
92
+
93
+ IO.readlines(link).each { |line|
94
+ if line =~ rgx
95
+ classes << $1.to_s
96
+ end
97
+ }
98
+
99
+ classes
100
+ end
101
+
102
+ end